mirror of
https://github.com/sailfishos/ofono
synced 2025-11-25 20:01:05 +08:00
Compare commits
42 Commits
mer/1.17+g
...
mer/1.17+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3a18326e1 | ||
|
|
93e564d5e5 | ||
|
|
42847e03b5 | ||
|
|
2100a8d975 | ||
|
|
c393e63e4e | ||
|
|
b24bc9761b | ||
|
|
06daa7cf21 | ||
|
|
49215d60b2 | ||
|
|
f3f3b73d6f | ||
|
|
113d9424b5 | ||
|
|
2a8489c4d9 | ||
|
|
c4f968b87a | ||
|
|
537c7ae8b4 | ||
|
|
b320fc7f59 | ||
|
|
edf49e6e99 | ||
|
|
b7985a1d67 | ||
|
|
bbb2c68a72 | ||
|
|
bd3f7f35eb | ||
|
|
65bf1a24fa | ||
|
|
0c37015145 | ||
|
|
a8551cdce7 | ||
|
|
5bd2b96240 | ||
|
|
3bf309b887 | ||
|
|
c14b9bbf93 | ||
|
|
568bd615cd | ||
|
|
4d55f94015 | ||
|
|
95d06963cd | ||
|
|
479458138a | ||
|
|
c221d677d1 | ||
|
|
a32da19192 | ||
|
|
a20da10621 | ||
|
|
64c754c3b9 | ||
|
|
d64fd7dca7 | ||
|
|
f608c0821a | ||
|
|
7d29ef130a | ||
|
|
141eadee1d | ||
|
|
e84602d79c | ||
|
|
b63b6355d5 | ||
|
|
f7f007a122 | ||
|
|
5769656848 | ||
|
|
bbc276b4c7 | ||
|
|
4b79de53fe |
@@ -132,6 +132,7 @@ builtin_sources += drivers/ril/ril_call_barring.c \
|
||||
drivers/ril/ril_gprs_context.c \
|
||||
drivers/ril/ril_mce.c \
|
||||
drivers/ril/ril_modem.c \
|
||||
drivers/ril/ril_mtu.c \
|
||||
drivers/ril/ril_netreg.c \
|
||||
drivers/ril/ril_network.c \
|
||||
drivers/ril/ril_oem_raw.c \
|
||||
@@ -142,7 +143,8 @@ builtin_sources += drivers/ril/ril_call_barring.c \
|
||||
drivers/ril/ril_radio_settings.c \
|
||||
drivers/ril/ril_sim.c \
|
||||
drivers/ril/ril_sim_card.c \
|
||||
drivers/ril/ril_sim_dbus.c \
|
||||
drivers/ril/ril_sim_info.c \
|
||||
drivers/ril/ril_sim_info_dbus.c \
|
||||
drivers/ril/ril_sms.c \
|
||||
drivers/ril/ril_stk.c \
|
||||
drivers/ril/ril_ussd.c \
|
||||
|
||||
@@ -93,6 +93,11 @@ Properties boolean Present [readonly]
|
||||
|
||||
Contains the IMSI of the SIM, if available.
|
||||
|
||||
string ServiceProviderName [readonly, optional]
|
||||
|
||||
Contains the service provider name fetched from the
|
||||
SIM card, if available.
|
||||
|
||||
string MobileCountryCode [readonly, optional]
|
||||
|
||||
Contains the Mobile Country Code (MCC) of the home
|
||||
|
||||
@@ -158,23 +158,54 @@ enum ril_radio_tech {
|
||||
#define CALL_FAIL_FACILITY_REJECTED 29
|
||||
#define CALL_FAIL_NORMAL_UNSPECIFIED 31
|
||||
|
||||
/* see RIL_REQUEST_DEACTIVATE_DATA_CALL parameter */
|
||||
enum ril_data_call_fail_cause {
|
||||
PDP_FAIL_NONE = 0,
|
||||
PDP_FAIL_OPERATOR_BARRED = 0x08,
|
||||
PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A,
|
||||
PDP_FAIL_MISSING_UKNOWN_APN = 0x1B,
|
||||
PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C,
|
||||
PDP_FAIL_USER_AUTHENTICATION = 0x1D,
|
||||
PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E,
|
||||
PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F,
|
||||
PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20,
|
||||
PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21,
|
||||
PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22,
|
||||
PDP_FAIL_NSAPI_IN_USE = 0x23,
|
||||
PDP_FAIL_REGULAR_DEACTIVATION = 0x24,
|
||||
PDP_FAIL_ONLY_IPV4_ALLOWED = 0x32,
|
||||
PDP_FAIL_ONLY_IPV6_ALLOWED = 0x33,
|
||||
PDP_FAIL_ONLY_SINGLE_BEARER_ALLOWED = 0x34,
|
||||
PDP_FAIL_PROTOCOL_ERRORS = 0x6F,
|
||||
PDP_FAIL_VOICE_REGISTRATION_FAIL = -1,
|
||||
PDP_FAIL_DATA_REGISTRATION_FAIL = -2,
|
||||
PDP_FAIL_SIGNAL_LOST = -3,
|
||||
PDP_FAIL_PREF_RADIO_TECH_CHANGED = -4,
|
||||
PDP_FAIL_RADIO_POWER_OFF = -5,
|
||||
PDP_FAIL_TETHERED_CALL_ACTIVE = -6,
|
||||
PDP_FAIL_ERROR_UNSPECIFIED = 0xffff
|
||||
};
|
||||
|
||||
/* RIL_REQUEST_DEACTIVATE_DATA_CALL parameter */
|
||||
#define RIL_DEACTIVATE_DATA_CALL_NO_REASON 0
|
||||
#define RIL_DEACTIVATE_DATA_CALL_RADIO_SHUTDOWN 1
|
||||
|
||||
/* See RIL_REQUEST_SETUP_DATA_CALL */
|
||||
/* RIL_REQUEST_SETUP_DATA_CALL */
|
||||
enum ril_data_profile {
|
||||
RIL_DATA_PROFILE_DEFAULT = 0,
|
||||
RIL_DATA_PROFILE_TETHERED = 1,
|
||||
RIL_DATA_PROFILE_IMS = 2,
|
||||
RIL_DATA_PROFILE_FOTA = 3,
|
||||
RIL_DATA_PROFILE_CBS = 4,
|
||||
RIL_DATA_PROFILE_OEM_BASE = 1000,
|
||||
RIL_DATA_PROFILE_INVALID = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
#define RIL_DATA_PROFILE_DEFAULT 0
|
||||
#define RIL_DATA_PROFILE_TETHERED 1
|
||||
#define RIL_DATA_PROFILE_IMS 2
|
||||
#define RIL_DATA_PROFILE_FOTA 3 /* FOTA = Firmware Over the Air */
|
||||
#define RIL_DATA_PROFILE_CBS 4
|
||||
#define RIL_DATA_PROFILE_OEM_BASE 1000 /* Start of OEM-specific profiles */
|
||||
|
||||
#define RIL_AUTH_NONE 0
|
||||
#define RIL_AUTH_PAP 1
|
||||
#define RIL_AUTH_CHAP 2
|
||||
#define RIL_AUTH_BOTH 3
|
||||
enum ril_auth {
|
||||
RIL_AUTH_NONE = 0,
|
||||
RIL_AUTH_PAP = 1,
|
||||
RIL_AUTH_CHAP = 2,
|
||||
RIL_AUTH_BOTH = 3
|
||||
};
|
||||
|
||||
#define RIL_CARD_MAX_APPS 8
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,24 +17,81 @@
|
||||
#define RIL_DATA_H
|
||||
|
||||
#include "ril_types.h"
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
enum ril_data_call_active {
|
||||
RIL_DATA_CALL_INACTIVE = 0,
|
||||
RIL_DATA_CALL_LINK_DOWN = 1,
|
||||
RIL_DATA_CALL_ACTIVE = 2
|
||||
};
|
||||
|
||||
struct ril_data_call {
|
||||
int cid;
|
||||
enum ril_data_call_fail_cause status;
|
||||
enum ril_data_call_active active;
|
||||
enum ofono_gprs_proto prot;
|
||||
int retry_time;
|
||||
int mtu;
|
||||
char *ifname;
|
||||
char **dnses;
|
||||
char **gateways;
|
||||
char **addresses;
|
||||
};
|
||||
|
||||
struct ril_data_call_list {
|
||||
guint version;
|
||||
guint num;
|
||||
GSList *calls;
|
||||
};
|
||||
|
||||
struct ril_data {
|
||||
GObject object;
|
||||
struct ril_data_priv *priv;
|
||||
struct ril_data_call_list *data_calls;
|
||||
};
|
||||
|
||||
struct ril_data_manager;
|
||||
struct ril_data_manager *ril_data_manager_new(void);
|
||||
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
|
||||
void ril_data_manager_unref(struct ril_data_manager *dm);
|
||||
|
||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, GRilIoChannel *io);
|
||||
typedef void (*ril_data_cb_t)(struct ril_data *data, void *arg);
|
||||
typedef void (*ril_data_call_setup_cb_t)(struct ril_data *data,
|
||||
int ril_status, const struct ril_data_call *call,
|
||||
void *arg);
|
||||
typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
||||
int ril_status, void *arg);
|
||||
|
||||
struct ril_data *ril_data_new(struct ril_data_manager *dm,
|
||||
struct ril_radio *radio, struct ril_network *network,
|
||||
GRilIoChannel *io);
|
||||
struct ril_data *ril_data_ref(struct ril_data *data);
|
||||
void ril_data_unref(struct ril_data *data);
|
||||
void ril_data_set_name(struct ril_data *data, const char *name);
|
||||
void ril_data_allow(struct ril_data *data, gboolean allow);
|
||||
gboolean ril_data_allowed(struct ril_data *data);
|
||||
|
||||
typedef void (*ril_data_cb_t)(struct ril_data *data, void *arg);
|
||||
gulong ril_data_add_allow_changed_handler(struct ril_data *data,
|
||||
ril_data_cb_t cb, void *arg);
|
||||
gulong ril_data_add_calls_changed_handler(struct ril_data *data,
|
||||
ril_data_cb_t cb, void *arg);
|
||||
void ril_data_remove_handler(struct ril_data *data, gulong id);
|
||||
|
||||
void ril_data_allow(struct ril_data *data, gboolean allow);
|
||||
|
||||
struct ril_data_call_request;
|
||||
struct ril_data_call_request *ril_data_call_setup(struct ril_data *data,
|
||||
const struct ofono_gprs_primary_context *ctx,
|
||||
ril_data_call_setup_cb_t cb, void *arg);
|
||||
struct ril_data_call_request *ril_data_call_deactivate(struct ril_data *data,
|
||||
int cid, ril_data_call_deactivate_cb_t cb, void *arg);
|
||||
void ril_data_call_request_detach(struct ril_data_call_request *req);
|
||||
void ril_data_call_request_cancel(struct ril_data_call_request *req);
|
||||
|
||||
void ril_data_call_free(struct ril_data_call *call);
|
||||
struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
|
||||
struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,
|
||||
int cid);
|
||||
|
||||
#endif /* RIL_DATA_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,122 +15,46 @@
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_network.h"
|
||||
#include "ril_data.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_mtu.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define PROTO_IP_STR "IP"
|
||||
#define PROTO_IPV6_STR "IPV6"
|
||||
#define PROTO_IPV4V6_STR "IPV4V6"
|
||||
|
||||
#define MIN_DATA_CALL_LIST_SIZE 8
|
||||
#define MIN_DATA_CALL_REPLY_SIZE 36
|
||||
|
||||
#define SETUP_DATA_CALL_PARAMS 7
|
||||
#define DATA_PROFILE_DEFAULT_STR "0"
|
||||
#define DEACTIVATE_DATA_CALL_PARAMS 2
|
||||
|
||||
#define CTX_ID_NONE ((unsigned int)(-1))
|
||||
|
||||
enum data_call_state {
|
||||
DATA_CALL_INACTIVE,
|
||||
DATA_CALL_LINK_DOWN,
|
||||
DATA_CALL_ACTIVE,
|
||||
};
|
||||
#define MAX_MTU 1280
|
||||
|
||||
enum ril_gprs_context_state {
|
||||
STATE_IDLE,
|
||||
STATE_ACTIVATING,
|
||||
STATE_DEACTIVATING,
|
||||
STATE_ACTIVE,
|
||||
struct ril_gprs_context_call {
|
||||
struct ril_data_call_request *req;
|
||||
ofono_gprs_context_cb_t cb;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct ril_gprs_context {
|
||||
struct ofono_gprs_context *gc;
|
||||
struct ril_modem *modem;
|
||||
struct ril_network *network;
|
||||
GRilIoChannel *io;
|
||||
GRilIoQueue *q;
|
||||
struct ril_data *data;
|
||||
guint active_ctx_cid;
|
||||
enum ril_gprs_context_state state;
|
||||
gulong regid;
|
||||
struct ril_gprs_context_data_call *active_call;
|
||||
struct ril_gprs_context_deactivate_req *deactivate_req;
|
||||
gulong calls_changed_event_id;
|
||||
struct ril_mtu_watch *mtu_watch;
|
||||
struct ril_data_call *active_call;
|
||||
struct ril_gprs_context_call activate;
|
||||
struct ril_gprs_context_call deactivate;
|
||||
};
|
||||
|
||||
struct ril_gprs_context_data_call {
|
||||
guint status;
|
||||
gint cid;
|
||||
guint active;
|
||||
int retry_time;
|
||||
int prot;
|
||||
gint mtu;
|
||||
gchar *ifname;
|
||||
gchar **dnses;
|
||||
gchar **gateways;
|
||||
gchar **addresses;
|
||||
};
|
||||
|
||||
struct ril_gprs_context_data_call_list {
|
||||
guint version;
|
||||
guint num;
|
||||
GSList *calls;
|
||||
};
|
||||
|
||||
struct ril_gprs_context_cbd {
|
||||
struct ril_gprs_context *gcd;
|
||||
ofono_gprs_context_cb_t cb;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct ril_gprs_context_deactivate_req {
|
||||
struct ril_gprs_context_cbd cbd;
|
||||
gint cid;
|
||||
};
|
||||
|
||||
#define ril_gprs_context_cbd_free g_free
|
||||
#define ril_gprs_context_deactivate_req_free g_free
|
||||
|
||||
static inline struct ril_gprs_context *ril_gprs_context_get_data(
|
||||
struct ofono_gprs_context *gprs)
|
||||
{
|
||||
return ofono_gprs_context_get_data(gprs);
|
||||
}
|
||||
|
||||
static struct ril_gprs_context_cbd *ril_gprs_context_cbd_new(
|
||||
struct ril_gprs_context *gcd, ofono_gprs_context_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_gprs_context_cbd *cbd =
|
||||
g_new0(struct ril_gprs_context_cbd, 1);
|
||||
|
||||
cbd->gcd = gcd;
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static struct ril_gprs_context_deactivate_req *
|
||||
ril_gprs_context_deactivate_req_new(struct ril_gprs_context *gcd,
|
||||
ofono_gprs_context_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_gprs_context_deactivate_req *req =
|
||||
g_new0(struct ril_gprs_context_deactivate_req, 1);
|
||||
|
||||
req->cbd.gcd = gcd;
|
||||
req->cbd.cb = cb;
|
||||
req->cbd.data = data;
|
||||
req->cid = gcd->active_call->cid;
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
static char *ril_gprs_context_netmask(const char *address)
|
||||
{
|
||||
if (address) {
|
||||
@@ -152,34 +76,6 @@ static char *ril_gprs_context_netmask(const char *address)
|
||||
return g_strdup("255.255.255.0");
|
||||
}
|
||||
|
||||
static const char *ril_gprs_ofono_protocol_to_ril(guint protocol)
|
||||
{
|
||||
switch (protocol) {
|
||||
case OFONO_GPRS_PROTO_IPV6:
|
||||
return PROTO_IPV6_STR;
|
||||
case OFONO_GPRS_PROTO_IPV4V6:
|
||||
return PROTO_IPV4V6_STR;
|
||||
case OFONO_GPRS_PROTO_IP:
|
||||
return PROTO_IP_STR;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ril_gprs_protocol_to_ofono(gchar *protocol_str)
|
||||
{
|
||||
if (protocol_str) {
|
||||
if (!strcmp(protocol_str, PROTO_IPV6_STR)) {
|
||||
return OFONO_GPRS_PROTO_IPV6;
|
||||
} else if (!strcmp(protocol_str, PROTO_IPV4V6_STR)) {
|
||||
return OFONO_GPRS_PROTO_IPV4V6;
|
||||
} else if (!strcmp(protocol_str, PROTO_IP_STR)) {
|
||||
return OFONO_GPRS_PROTO_IP;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_ipv4(struct ofono_gprs_context *gc,
|
||||
char * const *ip_addr)
|
||||
{
|
||||
@@ -209,34 +105,67 @@ static void ril_gprs_context_set_ipv6(struct ofono_gprs_context *gc,
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_data_call_free(
|
||||
struct ril_gprs_context_data_call *call)
|
||||
static void ril_gprs_context_call_done(struct ril_gprs_context_call *call,
|
||||
gboolean ok)
|
||||
{
|
||||
ofono_gprs_context_cb_t cb = call->cb;
|
||||
gpointer data = call->data;
|
||||
|
||||
ril_data_call_request_cancel(call->req);
|
||||
|
||||
call->req = NULL;
|
||||
call->cb = NULL;
|
||||
call->data = NULL;
|
||||
|
||||
if (cb) {
|
||||
struct ofono_error error;
|
||||
cb(ok ? ril_error_ok(&error) : ril_error_failure(&error), data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
|
||||
{
|
||||
if (gcd->active_call) {
|
||||
ril_data_call_free(gcd->active_call);
|
||||
gcd->active_call = NULL;
|
||||
}
|
||||
if (gcd->calls_changed_event_id) {
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||
gcd->calls_changed_event_id = 0;
|
||||
}
|
||||
if (gcd->mtu_watch) {
|
||||
ril_mtu_watch_free(gcd->mtu_watch);
|
||||
gcd->mtu_watch = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_active_call(struct ril_gprs_context *gcd,
|
||||
const struct ril_data_call *call)
|
||||
{
|
||||
if (call) {
|
||||
g_free(call->ifname);
|
||||
g_strfreev(call->dnses);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->gateways);
|
||||
g_free(call);
|
||||
ril_data_call_free(gcd->active_call);
|
||||
gcd->active_call = ril_data_call_dup(call);
|
||||
if (!gcd->mtu_watch) {
|
||||
gcd->mtu_watch = ril_mtu_watch_new(MAX_MTU);
|
||||
}
|
||||
ril_mtu_watch_set_ifname(gcd->mtu_watch, call->ifname);
|
||||
} else {
|
||||
ril_gprs_context_free_active_call(gcd);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
||||
{
|
||||
gcd->state = STATE_IDLE;
|
||||
if (gcd->active_call) {
|
||||
if (gcd->deactivate_req &&
|
||||
gcd->deactivate_req->cid == gcd->active_call->cid) {
|
||||
/* Mark this request as done */
|
||||
gcd->deactivate_req->cbd.gcd = NULL;
|
||||
gcd->deactivate_req = NULL;
|
||||
ril_gprs_context_free_active_call(gcd);
|
||||
if (gcd->deactivate.req) {
|
||||
ril_gprs_context_call_done(&gcd->deactivate, TRUE);
|
||||
}
|
||||
ril_gprs_context_data_call_free(gcd->active_call);
|
||||
gcd->active_call = NULL;
|
||||
}
|
||||
if (gcd->active_ctx_cid != CTX_ID_NONE) {
|
||||
guint id = gcd->active_ctx_cid;
|
||||
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||
DBG("ofono context %u deactivated", id);
|
||||
ofono_gprs_context_deactivated(gcd->gc, id);
|
||||
}
|
||||
}
|
||||
@@ -316,57 +245,10 @@ static void ril_gprs_split_dns_by_protocol(char **dns_array, char ***dns_addr,
|
||||
}
|
||||
}
|
||||
|
||||
static gint ril_gprs_context_parse_data_call_compare(gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const struct ril_gprs_context_data_call *ca = a;
|
||||
const struct ril_gprs_context_data_call *cb = b;
|
||||
|
||||
if (ca->cid < cb->cid) {
|
||||
return -1;
|
||||
} else if (ca->cid > cb->cid) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_data_call_free1(gpointer data)
|
||||
{
|
||||
ril_gprs_context_data_call_free(data);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_data_call_list_free(
|
||||
struct ril_gprs_context_data_call_list *list)
|
||||
{
|
||||
if (list) {
|
||||
g_slist_free_full(list->calls, ril_gprs_context_data_call_free1);
|
||||
g_free(list);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ril_gprs_context_data_call *ril_gprs_context_data_call_find(
|
||||
struct ril_gprs_context_data_call_list *list, gint cid)
|
||||
{
|
||||
if (list) {
|
||||
GSList *entry;
|
||||
|
||||
for (entry = list->calls; entry; entry = entry->next) {
|
||||
struct ril_gprs_context_data_call *call = entry->data;
|
||||
|
||||
if (call->cid == cid) {
|
||||
return call;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Only compares the stuff that's important to us */
|
||||
static gboolean ril_gprs_context_data_call_equal(
|
||||
const struct ril_gprs_context_data_call *c1,
|
||||
const struct ril_gprs_context_data_call *c2)
|
||||
const struct ril_data_call *c1,
|
||||
const struct ril_data_call *c2)
|
||||
{
|
||||
if (!c1 && !c2) {
|
||||
return TRUE;
|
||||
@@ -382,134 +264,58 @@ static gboolean ril_gprs_context_data_call_equal(
|
||||
}
|
||||
}
|
||||
|
||||
static struct ril_gprs_context_data_call *
|
||||
ril_gprs_context_parse_data_call(int version, GRilIoParser *rilp)
|
||||
static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
|
||||
{
|
||||
char *prot;
|
||||
struct ril_gprs_context_data_call *call =
|
||||
g_new0(struct ril_gprs_context_data_call, 1);
|
||||
|
||||
grilio_parser_get_uint32(rilp, &call->status);
|
||||
grilio_parser_get_int32(rilp, &call->retry_time);
|
||||
grilio_parser_get_int32(rilp, &call->cid);
|
||||
grilio_parser_get_uint32(rilp, &call->active);
|
||||
prot = grilio_parser_get_utf8(rilp);
|
||||
call->ifname = grilio_parser_get_utf8(rilp);
|
||||
call->addresses = grilio_parser_split_utf8(rilp, " ");
|
||||
call->dnses = grilio_parser_split_utf8(rilp, " ");
|
||||
call->gateways = grilio_parser_split_utf8(rilp, " ");
|
||||
|
||||
call->prot = ril_gprs_protocol_to_ofono(prot);
|
||||
if (call->prot < 0) {
|
||||
ofono_error("Invalid type(protocol) specified: %s", prot);
|
||||
}
|
||||
|
||||
g_free(prot);
|
||||
|
||||
if (version >= 9) {
|
||||
/* PCSCF */
|
||||
grilio_parser_skip_string(rilp);
|
||||
if (version >= 11) {
|
||||
/* MTU */
|
||||
grilio_parser_get_int32(rilp, &call->mtu);
|
||||
}
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
static struct ril_gprs_context_data_call_list *
|
||||
ril_gprs_context_parse_data_call_list(const void *data, guint len)
|
||||
{
|
||||
struct ril_gprs_context_data_call_list *reply =
|
||||
g_new0(struct ril_gprs_context_data_call_list, 1);
|
||||
GRilIoParser rilp;
|
||||
unsigned int i, n;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
grilio_parser_get_uint32(&rilp, &reply->version);
|
||||
grilio_parser_get_uint32(&rilp, &n);
|
||||
DBG("version=%d,num=%d", reply->version, n);
|
||||
|
||||
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
|
||||
struct ril_gprs_context_data_call *call =
|
||||
ril_gprs_context_parse_data_call(reply->version, &rilp);
|
||||
|
||||
DBG("%d [status=%d,retry=%d,cid=%d,"
|
||||
"active=%d,type=%s,ifname=%s,mtu=%d,"
|
||||
"address=%s, dns=%s %s,gateways=%s]",
|
||||
i, call->status, call->retry_time,
|
||||
call->cid, call->active,
|
||||
ril_gprs_ofono_protocol_to_ril(call->prot),
|
||||
call->ifname, call->mtu, call->addresses[0],
|
||||
call->dnses[0],
|
||||
(call->dnses[0] && call->dnses[1]) ?
|
||||
call->dnses[1] : "",
|
||||
call->gateways[0]);
|
||||
|
||||
reply->num++;
|
||||
reply->calls = g_slist_insert_sorted(reply->calls, call,
|
||||
ril_gprs_context_parse_data_call_compare);
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
static void ril_gprs_context_call_list_changed(GRilIoChannel *io, guint event,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_gprs_context *gcd = user_data;
|
||||
struct ril_gprs_context *gcd = arg;
|
||||
struct ofono_gprs_context *gc = gcd->gc;
|
||||
struct ril_gprs_context_data_call *call = NULL;
|
||||
struct ril_gprs_context_data_call *prev_call;
|
||||
struct ril_gprs_context_data_call_list *unsol =
|
||||
ril_gprs_context_parse_data_call_list(data, len);
|
||||
|
||||
if (gcd->active_call) {
|
||||
/* Find our call */
|
||||
call = ril_gprs_context_data_call_find(unsol,
|
||||
gcd->active_call->cid);
|
||||
if (call) {
|
||||
/* Check if the call have been disconnected */
|
||||
if (call->active == DATA_CALL_INACTIVE) {
|
||||
ofono_error("Clearing active context");
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
call = NULL;
|
||||
/*
|
||||
* gcd->active_call can't be NULL here because this callback
|
||||
* is only registered when we have the active call and released
|
||||
* when active call is dropped.
|
||||
*/
|
||||
struct ril_data_call *prev_call = gcd->active_call;
|
||||
const struct ril_data_call *call =
|
||||
ril_data_call_find(data->data_calls, prev_call->cid);
|
||||
|
||||
/* Compare it agains the last known state */
|
||||
} else if (ril_gprs_context_data_call_equal(call,
|
||||
gcd->active_call)) {
|
||||
DBG("call %u didn't change", call->cid);
|
||||
call = NULL;
|
||||
} else {
|
||||
/* Steal it from the list */
|
||||
DBG("call %u changed", call->cid);
|
||||
unsol->calls = g_slist_remove(unsol->calls,
|
||||
call);
|
||||
}
|
||||
} else {
|
||||
if (call) {
|
||||
/* Check if the call has been disconnected */
|
||||
if (call->active == RIL_DATA_CALL_INACTIVE) {
|
||||
ofono_error("Clearing active context");
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
}
|
||||
}
|
||||
call = NULL;
|
||||
|
||||
/* We don't need the rest of the list anymore */
|
||||
ril_gprs_context_data_call_list_free(unsol);
|
||||
/* Compare it against the last known state */
|
||||
} else if (ril_gprs_context_data_call_equal(call, prev_call)) {
|
||||
DBG("call %u didn't change", call->cid);
|
||||
call = NULL;
|
||||
|
||||
} else {
|
||||
DBG("call %u changed", call->cid);
|
||||
}
|
||||
} else {
|
||||
ofono_error("Clearing active context");
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
}
|
||||
|
||||
if (!call) {
|
||||
/* We are not interested */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store the updated call data */
|
||||
prev_call = gcd->active_call;
|
||||
gcd->active_call = call;
|
||||
/*
|
||||
* prev_call points to the previous active call, and it will
|
||||
* be deallocated at the end of the this function. Clear the
|
||||
* gcd->active_call pointer so that we don't deallocate it twice.
|
||||
*/
|
||||
gcd->active_call = NULL;
|
||||
ril_gprs_context_set_active_call(gcd, call);
|
||||
|
||||
if (call->status != 0) {
|
||||
if (call->status != PDP_FAIL_NONE) {
|
||||
ofono_info("data call status: %d", call->status);
|
||||
}
|
||||
|
||||
if (call->active == DATA_CALL_ACTIVE) {
|
||||
if (call->active == RIL_DATA_CALL_ACTIVE) {
|
||||
gboolean signal = FALSE;
|
||||
|
||||
if (call->ifname && g_strcmp0(call->ifname, prev_call->ifname)) {
|
||||
@@ -605,51 +411,37 @@ static void ril_gprs_context_call_list_changed(GRilIoChannel *io, guint event,
|
||||
}
|
||||
}
|
||||
|
||||
ril_gprs_context_data_call_free(prev_call);
|
||||
ril_data_call_free(prev_call);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_activate_primary_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
||||
int ril_status, const struct ril_data_call *call,
|
||||
void *user_data)
|
||||
{
|
||||
struct ril_gprs_context_cbd *cbd = user_data;
|
||||
ofono_gprs_context_cb_t cb = cbd->cb;
|
||||
struct ril_gprs_context *gcd = cbd->gcd;
|
||||
struct ril_gprs_context *gcd = user_data;
|
||||
struct ofono_gprs_context *gc = gcd->gc;
|
||||
struct ofono_error error;
|
||||
struct ril_gprs_context_data_call_list *reply = NULL;
|
||||
struct ril_gprs_context_data_call *call;
|
||||
char **split_ip_addr = NULL;
|
||||
char **split_ipv6_addr = NULL;
|
||||
char* ip_gw = NULL;
|
||||
char* ipv6_gw = NULL;
|
||||
char** dns_addr = NULL;
|
||||
char** dns_ipv6_addr = NULL;
|
||||
ofono_gprs_context_cb_t cb;
|
||||
gpointer cb_data;
|
||||
|
||||
ofono_info("setting up data call");
|
||||
|
||||
ril_error_init_ok(&error);
|
||||
if (status != RIL_E_SUCCESS) {
|
||||
ril_error_init_failure(&error);
|
||||
if (ril_status != RIL_E_SUCCESS) {
|
||||
ofono_error("GPRS context: Reply failure: %s",
|
||||
ril_error_to_string(status));
|
||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
||||
error.error = status;
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
ril_error_to_string(ril_status));
|
||||
goto done;
|
||||
}
|
||||
|
||||
reply = ril_gprs_context_parse_data_call_list(data, len);
|
||||
if (reply->num != 1) {
|
||||
ofono_error("Number of data calls: %u", reply->num);
|
||||
ril_error_init_failure(&error);
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
call = reply->calls->data;
|
||||
|
||||
if (call->status != 0) {
|
||||
if (call->status != PDP_FAIL_NONE) {
|
||||
ofono_error("Unexpected data call status %d", call->status);
|
||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
||||
error.type = OFONO_ERROR_TYPE_CMS;
|
||||
error.error = call->status;
|
||||
goto done;
|
||||
}
|
||||
@@ -657,9 +449,6 @@ static void ril_gprs_context_activate_primary_cb(GRilIoChannel *io, int status,
|
||||
/* Must have interface */
|
||||
if (!call->ifname) {
|
||||
ofono_error("GPRS context: No interface");
|
||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
||||
error.error = EINVAL;
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -668,35 +457,25 @@ static void ril_gprs_context_activate_primary_cb(GRilIoChannel *io, int status,
|
||||
&split_ipv6_addr);
|
||||
if (!split_ip_addr && !split_ipv6_addr) {
|
||||
ofono_error("GPRS context: No IP address");
|
||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
||||
error.error = EINVAL;
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Steal the call data from the list */
|
||||
g_slist_free(reply->calls);
|
||||
reply->calls = NULL;
|
||||
ril_gprs_context_data_call_free(gcd->active_call);
|
||||
gcd->active_call = call;
|
||||
gcd->state = STATE_ACTIVE;
|
||||
ril_error_init_ok(&error);
|
||||
ril_gprs_context_set_active_call(gcd, call);
|
||||
|
||||
GASSERT(!gcd->calls_changed_event_id);
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||
gcd->calls_changed_event_id =
|
||||
ril_data_add_calls_changed_handler(gcd->data,
|
||||
ril_gprs_context_call_list_changed, gcd);
|
||||
|
||||
ofono_gprs_context_set_interface(gc, call->ifname);
|
||||
ril_gprs_split_gw_by_protocol(call->gateways, &ip_gw, &ipv6_gw);
|
||||
ril_gprs_split_dns_by_protocol(call->dnses, &dns_addr, &dns_ipv6_addr);
|
||||
|
||||
/* TODO:
|
||||
* RILD can return multiple addresses; oFono only supports setting
|
||||
* a single IPv4 and single IPV6 address. At this time, we only use
|
||||
* the first address. It's possible that a RIL may just specify
|
||||
* the end-points of the point-to-point connection, in which case this
|
||||
* code will need to changed to handle such a device.
|
||||
*/
|
||||
|
||||
if (split_ipv6_addr &&
|
||||
(call->prot == OFONO_GPRS_PROTO_IPV6 ||
|
||||
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
|
||||
|
||||
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
|
||||
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
||||
ofono_gprs_context_set_ipv6_dns_servers(gc,
|
||||
@@ -713,7 +492,6 @@ static void ril_gprs_context_activate_primary_cb(GRilIoChannel *io, int status,
|
||||
}
|
||||
|
||||
done:
|
||||
ril_gprs_context_data_call_list_free(reply);
|
||||
g_strfreev(split_ip_addr);
|
||||
g_strfreev(split_ipv6_addr);
|
||||
g_strfreev(dns_addr);
|
||||
@@ -721,7 +499,17 @@ done:
|
||||
g_free(ip_gw);
|
||||
g_free(ipv6_gw);
|
||||
|
||||
cb(&error, cbd->data);
|
||||
cb = gcd->activate.cb;
|
||||
cb_data = gcd->activate.data;
|
||||
GASSERT(gcd->activate.req);
|
||||
memset(&gcd->activate, 0, sizeof(gcd->activate));
|
||||
|
||||
if (cb) {
|
||||
if (error.type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||
}
|
||||
cb(&error, cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
|
||||
@@ -730,14 +518,11 @@ static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
|
||||
{
|
||||
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
||||
struct ofono_netreg *netreg = ril_modem_ofono_netreg(gcd->modem);
|
||||
struct ofono_gprs *gprs = ril_modem_ofono_gprs(gcd->modem);
|
||||
const int rs = ofono_netreg_get_status(netreg);
|
||||
const gchar *protocol_str;
|
||||
GRilIoRequest* req;
|
||||
int tech, auth;
|
||||
|
||||
/* Let's make sure that we aren't connecting when roaming not allowed */
|
||||
if (rs == NETWORK_REGISTRATION_STATUS_ROAMING) {
|
||||
struct ofono_gprs *gprs = ril_modem_ofono_gprs(gcd->modem);
|
||||
if (!ofono_gprs_get_roaming_allowed(gprs) &&
|
||||
ril_netreg_check_if_really_roaming(netreg, rs) ==
|
||||
NETWORK_REGISTRATION_STATUS_ROAMING) {
|
||||
@@ -750,135 +535,46 @@ static void ril_gprs_context_activate_primary(struct ofono_gprs_context *gc,
|
||||
}
|
||||
|
||||
ofono_info("Activating context: %d", ctx->cid);
|
||||
protocol_str = ril_gprs_ofono_protocol_to_ril(ctx->proto);
|
||||
GASSERT(protocol_str);
|
||||
|
||||
/* ril.h has this to say about the radio tech parameter:
|
||||
*
|
||||
* ((const char **)data)[0] Radio technology to use: 0-CDMA,
|
||||
* 1-GSM/UMTS, 2... for values above 2
|
||||
* this is RIL_RadioTechnology + 2.
|
||||
*
|
||||
* Makes little sense but it is what it is.
|
||||
*/
|
||||
tech = gcd->network->data.ril_tech;
|
||||
if (tech > 2) {
|
||||
tech += 2;
|
||||
} else {
|
||||
/*
|
||||
* This value used to be hardcoded, let's keep using it
|
||||
* as the default.
|
||||
*/
|
||||
tech = RADIO_TECH_HSPA;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do the same as in $AOSP/frameworks/opt/telephony/src/java/com/
|
||||
* android/internal/telephony/dataconnection/DataConnection.java,
|
||||
* onConnect(), and use authentication or not depending on whether
|
||||
* the user field is empty or not.
|
||||
*/
|
||||
auth = (ctx->username && ctx->username[0]) ?
|
||||
RIL_AUTH_BOTH : RIL_AUTH_NONE;
|
||||
|
||||
/*
|
||||
* TODO: add comments about tethering, other non-public
|
||||
* profiles...
|
||||
*/
|
||||
req = grilio_request_new();
|
||||
grilio_request_append_int32(req, SETUP_DATA_CALL_PARAMS);
|
||||
grilio_request_append_format(req, "%d", tech);
|
||||
grilio_request_append_utf8(req, DATA_PROFILE_DEFAULT_STR);
|
||||
grilio_request_append_utf8(req, ctx->apn);
|
||||
grilio_request_append_utf8(req, ctx->username);
|
||||
grilio_request_append_utf8(req, ctx->password);
|
||||
grilio_request_append_format(req, "%d", auth);
|
||||
grilio_request_append_utf8(req, protocol_str);
|
||||
|
||||
GASSERT(!gcd->activate.req);
|
||||
GASSERT(ctx->cid != CTX_ID_NONE);
|
||||
|
||||
gcd->active_ctx_cid = ctx->cid;
|
||||
gcd->state = STATE_ACTIVATING;
|
||||
|
||||
grilio_queue_send_request_full(gcd->q, req, RIL_REQUEST_SETUP_DATA_CALL,
|
||||
ril_gprs_context_activate_primary_cb, ril_gprs_context_cbd_free,
|
||||
ril_gprs_context_cbd_new(gcd, cb, data));
|
||||
grilio_request_unref(req);
|
||||
gcd->activate.cb = cb;
|
||||
gcd->activate.data = data;
|
||||
gcd->activate.req = ril_data_call_setup(gcd->data, ctx,
|
||||
ril_gprs_context_activate_primary_cb, gcd);
|
||||
}
|
||||
|
||||
static void ril_gprs_context_deactivate_data_call_cb(GRilIoChannel *io, int err,
|
||||
const void *data, guint len, void *user_data)
|
||||
static void ril_gprs_context_deactivate_primary_cb(struct ril_data *data,
|
||||
int ril_status, void *user_data)
|
||||
{
|
||||
struct ril_gprs_context *gcd = user_data;
|
||||
struct ofono_error error;
|
||||
struct ril_gprs_context_deactivate_req *req = user_data;
|
||||
struct ril_gprs_context *gcd = req->cbd.gcd;
|
||||
ofono_gprs_context_cb_t cb;
|
||||
gpointer cb_data;
|
||||
|
||||
if (!gcd) {
|
||||
/*
|
||||
* ril_gprs_context_remove() zeroes gcd pointer for the
|
||||
* pending ril_gprs_context_deactivate_req. Or we may have
|
||||
* received RIL_UNSOL_DATA_CALL_LIST_CHANGED event before
|
||||
* RIL_REQUEST_DEACTIVATE_DATA_CALL completes, in which
|
||||
* case gcd will also be NULL. In any case, it means that
|
||||
* there's nothing left for us to do here. Just ignore it.
|
||||
*/
|
||||
DBG("late completion, cid: %d err: %d", req->cid, err);
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
GASSERT(gcd->active_call);
|
||||
ril_error_init_ok(&error);
|
||||
ofono_info("Deactivated data call");
|
||||
} else {
|
||||
ofono_gprs_context_cb_t cb = req->cbd.cb;
|
||||
|
||||
/* Mark it as done */
|
||||
if (gcd->deactivate_req == req) {
|
||||
gcd->deactivate_req = NULL;
|
||||
}
|
||||
|
||||
if (err == RIL_E_SUCCESS) {
|
||||
GASSERT(gcd->active_call &&
|
||||
gcd->active_call->cid == req->cid);
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
ofono_info("Deactivated data call");
|
||||
if (cb) {
|
||||
cb(ril_error_ok(&error), req->cbd.data);
|
||||
}
|
||||
} else {
|
||||
ofono_error("Deactivate failure: %s",
|
||||
ril_error_to_string(err));
|
||||
if (cb) {
|
||||
cb(ril_error_failure(&error), req->cbd.data);
|
||||
}
|
||||
}
|
||||
ril_error_init_failure(&error);
|
||||
ofono_error("Deactivate failure: %s",
|
||||
ril_error_to_string(ril_status));
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_gprs_context_deactivate_data_call(struct ril_gprs_context *gcd,
|
||||
ofono_gprs_context_cb_t cb, void *data)
|
||||
{
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
cb = gcd->deactivate.cb;
|
||||
cb_data = gcd->deactivate.data;
|
||||
GASSERT(gcd->deactivate.req);
|
||||
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
|
||||
|
||||
/* Overlapping deactivate requests make no sense */
|
||||
GASSERT(!gcd->deactivate_req);
|
||||
if (gcd->deactivate_req) {
|
||||
gcd->deactivate_req->cbd.gcd = NULL;
|
||||
if (cb) {
|
||||
ril_gprs_context_free_active_call(gcd);
|
||||
cb(&error, cb_data);
|
||||
} else {
|
||||
/* Have to tell ofono that the call has been disconnected */
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
}
|
||||
gcd->deactivate_req =
|
||||
ril_gprs_context_deactivate_req_new(gcd, cb, data);
|
||||
|
||||
/* Caller is responsible for checking gcd->active_call */
|
||||
GASSERT(gcd->active_call);
|
||||
grilio_request_append_int32(req, DEACTIVATE_DATA_CALL_PARAMS);
|
||||
grilio_request_append_format(req, "%d", gcd->active_call->cid);
|
||||
grilio_request_append_format(req, "%d",
|
||||
RIL_DEACTIVATE_DATA_CALL_NO_REASON);
|
||||
|
||||
/*
|
||||
* Send it to GRilIoChannel so that it doesn't get cancelled
|
||||
* by ril_gprs_context_remove()
|
||||
*/
|
||||
grilio_channel_send_request_full(gcd->io, req,
|
||||
RIL_REQUEST_DEACTIVATE_DATA_CALL,
|
||||
ril_gprs_context_deactivate_data_call_cb,
|
||||
ril_gprs_context_deactivate_req_free,
|
||||
gcd->deactivate_req);
|
||||
grilio_request_unref(req);
|
||||
gcd->state = STATE_DEACTIVATING;
|
||||
}
|
||||
|
||||
static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
||||
@@ -886,13 +582,16 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
||||
{
|
||||
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
||||
|
||||
GASSERT(cb);
|
||||
GASSERT(gcd->active_call && gcd->active_ctx_cid == id);
|
||||
ofono_info("Deactivate primary");
|
||||
|
||||
if (gcd->active_call && gcd->active_ctx_cid == id) {
|
||||
ril_gprs_context_deactivate_data_call(gcd, cb, data);
|
||||
} else {
|
||||
gcd->deactivate.cb = cb;
|
||||
gcd->deactivate.data = data;
|
||||
gcd->deactivate.req = ril_data_call_deactivate(gcd->data,
|
||||
gcd->active_call->cid,
|
||||
ril_gprs_context_deactivate_primary_cb, gcd);
|
||||
} else if (cb) {
|
||||
struct ofono_error error;
|
||||
cb(ril_error_ok(&error), data);
|
||||
}
|
||||
@@ -901,13 +600,8 @@ static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
||||
static void ril_gprs_context_detach_shutdown(struct ofono_gprs_context *gc,
|
||||
unsigned int id)
|
||||
{
|
||||
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
||||
|
||||
DBG("%d", id);
|
||||
GASSERT(gcd->active_ctx_cid == id);
|
||||
if (gcd->active_call && !gcd->deactivate_req) {
|
||||
ril_gprs_context_deactivate_data_call(gcd, NULL, NULL);
|
||||
}
|
||||
ril_gprs_context_deactivate_primary(gc, id, NULL, NULL);
|
||||
}
|
||||
|
||||
static int ril_gprs_context_probe(struct ofono_gprs_context *gc,
|
||||
@@ -920,12 +614,8 @@ static int ril_gprs_context_probe(struct ofono_gprs_context *gc,
|
||||
gcd->gc = gc;
|
||||
gcd->modem = modem;
|
||||
gcd->network = ril_network_ref(modem->network);
|
||||
gcd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||
gcd->q = grilio_queue_new(gcd->io);
|
||||
gcd->regid = grilio_channel_add_unsol_event_handler(gcd->io,
|
||||
ril_gprs_context_call_list_changed,
|
||||
RIL_UNSOL_DATA_CALL_LIST_CHANGED, gcd);
|
||||
ril_gprs_context_set_disconnected(gcd);
|
||||
gcd->data = ril_data_ref(modem->data);
|
||||
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||
ofono_gprs_context_set_data(gc, gcd);
|
||||
return 0;
|
||||
}
|
||||
@@ -937,20 +627,21 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
||||
DBG("");
|
||||
ofono_gprs_context_set_data(gc, NULL);
|
||||
|
||||
if (gcd->active_call && !gcd->deactivate_req) {
|
||||
ril_gprs_context_deactivate_data_call(gcd, NULL, NULL);
|
||||
}
|
||||
|
||||
if (gcd->deactivate_req) {
|
||||
gcd->deactivate_req->cbd.gcd = NULL;
|
||||
ril_data_call_request_cancel(gcd->activate.req);
|
||||
|
||||
if (gcd->deactivate.req) {
|
||||
/* Let it complete but we won't be around to be notified. */
|
||||
ril_data_call_request_detach(gcd->deactivate.req);
|
||||
} else if (gcd->active_call) {
|
||||
ril_data_call_deactivate(gcd->data, gcd->active_call->cid,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||
ril_data_unref(gcd->data);
|
||||
ril_network_unref(gcd->network);
|
||||
grilio_channel_remove_handler(gcd->io, gcd->regid);
|
||||
grilio_channel_unref(gcd->io);
|
||||
grilio_queue_cancel_all(gcd->q, FALSE);
|
||||
grilio_queue_unref(gcd->q);
|
||||
ril_gprs_context_data_call_free(gcd->active_call);
|
||||
ril_data_call_free(gcd->active_call);
|
||||
ril_mtu_watch_free(gcd->mtu_watch);
|
||||
g_free(gcd);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ struct ril_modem_data {
|
||||
ril_modem_cb_t removed_cb;
|
||||
void *removed_cb_data;
|
||||
|
||||
ril_modem_online_cb_t online_cb;
|
||||
void *online_cb_data;
|
||||
|
||||
struct ril_modem_online_request set_online;
|
||||
struct ril_modem_online_request set_offline;
|
||||
};
|
||||
@@ -127,6 +130,15 @@ void ril_modem_set_removed_cb(struct ril_modem *modem, ril_modem_cb_t cb,
|
||||
md->removed_cb_data = data;
|
||||
}
|
||||
|
||||
void ril_modem_set_online_cb(struct ril_modem *modem, ril_modem_online_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct ril_modem_data *md = ril_modem_data_from_modem(modem);
|
||||
|
||||
md->online_cb = cb;
|
||||
md->online_cb_data = data;
|
||||
}
|
||||
|
||||
static void ril_modem_check_devinfo(struct ril_modem_data *md)
|
||||
{
|
||||
/* devinfo driver assumes that IMEI is known */
|
||||
@@ -208,7 +220,8 @@ static gboolean ril_modem_online_request_timeout(gpointer data)
|
||||
req->data = NULL;
|
||||
cb(ril_error_failure(&error), cb_data);
|
||||
ril_modem_update_online_state(req->md);
|
||||
return FALSE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean ril_modem_online_check(gpointer data)
|
||||
@@ -251,7 +264,7 @@ static void ril_modem_radio_state_cb(struct ril_radio *radio, void *data)
|
||||
GASSERT(md->modem.radio == radio);
|
||||
ril_modem_update_radio_settings(md);
|
||||
ril_modem_update_online_state(md);
|
||||
};
|
||||
}
|
||||
|
||||
static void ril_modem_pre_sim(struct ofono_modem *modem)
|
||||
{
|
||||
@@ -320,6 +333,10 @@ static void ril_modem_set_online(struct ofono_modem *modem, ofono_bool_t online,
|
||||
DBG("%s going %sline", ofono_modem_get_path(modem),
|
||||
online ? "on" : "off");
|
||||
|
||||
if (md->online_cb) {
|
||||
md->online_cb(&md->modem, online, md->online_cb_data);
|
||||
}
|
||||
|
||||
if (online) {
|
||||
ril_radio_power_on(md->modem.radio, RADIO_POWER_TAG(md));
|
||||
req = &md->set_online;
|
||||
@@ -449,7 +466,6 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
||||
err = ofono_modem_register(ofono);
|
||||
if (!err) {
|
||||
ril_radio_power_cycle(modem->radio);
|
||||
ril_radio_power_on(modem->radio, RADIO_POWER_TAG(md));
|
||||
GASSERT(io->connected);
|
||||
|
||||
/*
|
||||
|
||||
223
ofono/drivers/ril/ril_mtu.c
Normal file
223
ofono/drivers/ril/ril_mtu.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "ril_mtu.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
struct ril_mtu_watch {
|
||||
int max_mtu;
|
||||
char *ifname;
|
||||
void *buf;
|
||||
int bufsize;
|
||||
GIOChannel *channel;
|
||||
guint io_watch;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static void ril_mtu_watch_limit_mtu(struct ril_mtu_watch *self)
|
||||
{
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (fd >= 0) {
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, self->ifname, IFNAMSIZ);
|
||||
if (ioctl(fd, SIOCGIFMTU, &ifr) < 0 ||
|
||||
ifr.ifr_mtu > self->max_mtu) {
|
||||
DBG("%s mtu %d => %d", self->ifname, ifr.ifr_mtu,
|
||||
self->max_mtu);
|
||||
ifr.ifr_mtu = self->max_mtu;
|
||||
if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
|
||||
ofono_error("Failed to set MTU");
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_mtu_watch_handle_rtattr(struct ril_mtu_watch *self,
|
||||
const struct rtattr *rta, int len)
|
||||
{
|
||||
int mtu = 0;
|
||||
const char *ifname = NULL;
|
||||
while (len > 0 && RTA_OK(rta, len) && (!mtu || !ifname)) {
|
||||
switch (rta->rta_type) {
|
||||
case IFLA_IFNAME:
|
||||
ifname = RTA_DATA(rta);
|
||||
break;
|
||||
case IFLA_MTU:
|
||||
mtu = *((int*)RTA_DATA(rta));
|
||||
break;
|
||||
}
|
||||
rta = RTA_NEXT(rta, len);
|
||||
}
|
||||
if (mtu > self->max_mtu && !g_strcmp0(ifname, self->ifname)) {
|
||||
DBG("%s %d", ifname, mtu);
|
||||
ril_mtu_watch_limit_mtu(self);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_mtu_watch_handle_ifinfomsg(struct ril_mtu_watch *self,
|
||||
const struct ifinfomsg *ifi, int len)
|
||||
{
|
||||
if (ifi->ifi_flags & IFF_UP) {
|
||||
const struct rtattr *rta = IFLA_RTA(ifi);
|
||||
ril_mtu_watch_handle_rtattr(self, rta,
|
||||
len - ((char*)rta - (char*)ifi));
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_mtu_watch_handle_nlmsg(struct ril_mtu_watch *self,
|
||||
const struct nlmsghdr *hdr, int len)
|
||||
{
|
||||
while (len > 0 && NLMSG_OK(hdr, len)) {
|
||||
if (hdr->nlmsg_type == RTM_NEWLINK) {
|
||||
ril_mtu_watch_handle_ifinfomsg(self, NLMSG_DATA(hdr),
|
||||
IFLA_PAYLOAD(hdr));
|
||||
}
|
||||
hdr = NLMSG_NEXT(hdr, len);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_mtu_watch_event(GIOChannel *ch, GIOCondition cond,
|
||||
gpointer data)
|
||||
{
|
||||
struct ril_mtu_watch *self = data;
|
||||
struct sockaddr_nl addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
ssize_t result = recvfrom(self->fd, self->buf, self->bufsize, 0,
|
||||
(struct sockaddr *)&addr, &addrlen);
|
||||
if (result > 0) {
|
||||
if (!addr.nl_pid) {
|
||||
ril_mtu_watch_handle_nlmsg(self, self->buf, result);
|
||||
}
|
||||
return G_SOURCE_CONTINUE;
|
||||
} else if (result == 0 || errno == EINTR || errno == EAGAIN) {
|
||||
return G_SOURCE_CONTINUE;
|
||||
} else {
|
||||
DBG("%s error %d", self->ifname, errno);
|
||||
self->io_watch = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_mtu_watch_open_socket(struct ril_mtu_watch *self)
|
||||
{
|
||||
GASSERT(self->fd < 0);
|
||||
self->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (self->fd >= 0) {
|
||||
struct sockaddr_nl nl;
|
||||
memset(&nl, 0, sizeof(nl));
|
||||
nl.nl_pid = getpid();
|
||||
nl.nl_family = AF_NETLINK;
|
||||
nl.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
|
||||
RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
|
||||
RTMGRP_LINK;
|
||||
|
||||
if (bind(self->fd, (struct sockaddr*)&nl, sizeof(nl)) >= 0) {
|
||||
return TRUE;
|
||||
}
|
||||
close(self->fd);
|
||||
self->fd = -1;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean ril_mtu_watch_start(struct ril_mtu_watch *self)
|
||||
{
|
||||
if (self->fd >= 0) {
|
||||
return TRUE;
|
||||
} else if (ril_mtu_watch_open_socket(self)) {
|
||||
GASSERT(!self->channel);
|
||||
GASSERT(!self->io_watch);
|
||||
self->channel = g_io_channel_unix_new(self->fd);
|
||||
if (self->channel) {
|
||||
g_io_channel_set_encoding(self->channel, NULL, NULL);
|
||||
g_io_channel_set_buffered(self->channel, FALSE);
|
||||
self->io_watch = g_io_add_watch(self->channel,
|
||||
G_IO_IN | G_IO_NVAL | G_IO_HUP,
|
||||
ril_mtu_watch_event, self);
|
||||
return TRUE;
|
||||
}
|
||||
close(self->fd);
|
||||
self->fd = -1;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_mtu_watch_stop(struct ril_mtu_watch *self)
|
||||
{
|
||||
if (self->io_watch) {
|
||||
g_source_remove(self->io_watch);
|
||||
self->io_watch = 0;
|
||||
}
|
||||
if (self->channel) {
|
||||
g_io_channel_shutdown(self->channel, TRUE, NULL);
|
||||
g_io_channel_unref(self->channel);
|
||||
self->channel = NULL;
|
||||
}
|
||||
if (self->fd >= 0) {
|
||||
close(self->fd);
|
||||
self->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct ril_mtu_watch *ril_mtu_watch_new(int max_mtu)
|
||||
{
|
||||
struct ril_mtu_watch *self = g_new0(struct ril_mtu_watch, 1);
|
||||
self->fd = -1;
|
||||
self->max_mtu = max_mtu;
|
||||
self->bufsize = 4096;
|
||||
self->buf = g_malloc(self->bufsize);
|
||||
return self;
|
||||
}
|
||||
|
||||
void ril_mtu_watch_free(struct ril_mtu_watch *self)
|
||||
{
|
||||
if (self) {
|
||||
ril_mtu_watch_stop(self);
|
||||
g_free(self->ifname);
|
||||
g_free(self->buf);
|
||||
g_free(self);
|
||||
}
|
||||
}
|
||||
|
||||
void ril_mtu_watch_set_ifname(struct ril_mtu_watch *self, const char *ifname)
|
||||
{
|
||||
if (self && g_strcmp0(self->ifname, ifname)) {
|
||||
g_free(self->ifname);
|
||||
if (ifname) {
|
||||
self->ifname = g_strdup(ifname);
|
||||
ril_mtu_watch_limit_mtu(self);
|
||||
ril_mtu_watch_start(self);
|
||||
} else {
|
||||
self->ifname = NULL;
|
||||
ril_mtu_watch_stop(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
33
ofono/drivers/ril/ril_mtu.h
Normal file
33
ofono/drivers/ril/ril_mtu.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef RIL_MTU_H
|
||||
#define RIL_MTU_H
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
struct ril_mtu_watch *ril_mtu_watch_new(int max_mtu);
|
||||
void ril_mtu_watch_free(struct ril_mtu_watch *mw);
|
||||
void ril_mtu_watch_set_ifname(struct ril_mtu_watch *mw, const char *ifname);
|
||||
|
||||
#endif /* RIL_MTU_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -164,7 +164,13 @@ static void ril_netreg_current_operator(struct ofono_netreg *netreg,
|
||||
{
|
||||
struct ril_netreg *nd = ril_netreg_get_data(netreg);
|
||||
|
||||
GASSERT(!nd->current_operator_id);
|
||||
/*
|
||||
* Calling ofono_netreg_status_notify() may result in
|
||||
* ril_netreg_current_operator() being invoked even if one
|
||||
* is already pending. Since ofono core doesn't associate
|
||||
* any context with individual calls, we can safely assume
|
||||
* that such a call essentially cancels the previous one.
|
||||
*/
|
||||
if (nd->current_operator_id) {
|
||||
g_source_remove(nd->current_operator_id);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ gulong ril_network_add_data_state_changed_handler(struct ril_network *net,
|
||||
ril_network_cb_t cb, void *arg);
|
||||
void ril_network_remove_handler(struct ril_network *net, gulong id);
|
||||
|
||||
#endif /* RIL_NETWORK */
|
||||
#endif /* RIL_NETWORK_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_sim_card.h"
|
||||
#include "ril_sim_info.h"
|
||||
#include "ril_network.h"
|
||||
#include "ril_radio.h"
|
||||
#include "ril_data.h"
|
||||
@@ -78,10 +79,12 @@ struct ril_plugin_priv {
|
||||
struct ril_data_manager *data_manager;
|
||||
GSList *slots;
|
||||
ril_slot_info_ptr *slots_info;
|
||||
struct ril_slot *data_slot;
|
||||
struct ril_slot *voice_slot;
|
||||
struct ril_slot *data_slot;
|
||||
struct ril_slot *mms_slot;
|
||||
char *default_voice_imsi;
|
||||
char *default_data_imsi;
|
||||
char *mms_imsi;
|
||||
GKeyFile *storage;
|
||||
};
|
||||
|
||||
@@ -95,15 +98,17 @@ struct ril_slot {
|
||||
gint timeout; /* RIL timeout, in milliseconds */
|
||||
int index;
|
||||
int sim_flags;
|
||||
gboolean online;
|
||||
struct ril_slot_config config;
|
||||
struct ril_plugin_priv *plugin;
|
||||
struct ril_sim_dbus *sim_dbus;
|
||||
struct ril_modem *modem;
|
||||
struct ril_mce *mce;
|
||||
struct ofono_sim *sim;
|
||||
struct ril_radio *radio;
|
||||
struct ril_network *network;
|
||||
struct ril_sim_card *sim_card;
|
||||
struct ril_sim_info *sim_info;
|
||||
struct ril_sim_info_dbus *sim_info_dbus;
|
||||
struct ril_data *data;
|
||||
GRilIoChannel *io;
|
||||
gulong io_event_id[IO_EVENT_COUNT];
|
||||
@@ -121,7 +126,6 @@ static void ril_debug_trace_notify(struct ofono_debug_desc *desc);
|
||||
static void ril_debug_dump_notify(struct ofono_debug_desc *desc);
|
||||
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc);
|
||||
static void ril_plugin_retry_init_io(struct ril_slot *slot);
|
||||
static void ril_plugin_update_modem_paths_full(struct ril_plugin_priv *plugin);
|
||||
|
||||
GLOG_MODULE_DEFINE("rilmodem");
|
||||
|
||||
@@ -181,6 +185,7 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
|
||||
ofono_sim_remove_state_watch(slot->sim,
|
||||
slot->sim_state_watch_id);
|
||||
}
|
||||
ril_sim_info_set_ofono_sim(slot->sim_info, NULL);
|
||||
slot->sim = NULL;
|
||||
}
|
||||
|
||||
@@ -321,6 +326,9 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
|
||||
{
|
||||
int mask = 0;
|
||||
struct ril_slot *slot = NULL;
|
||||
struct ril_slot *mms_slot = NULL;
|
||||
struct ril_slot *old_data_slot = NULL;
|
||||
struct ril_slot *new_data_slot = NULL;
|
||||
|
||||
/* Voice */
|
||||
if (plugin->default_voice_imsi) {
|
||||
@@ -373,23 +381,61 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
|
||||
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
|
||||
}
|
||||
|
||||
if (slot && !slot->online) {
|
||||
slot = NULL;
|
||||
}
|
||||
|
||||
if (plugin->mms_imsi) {
|
||||
mms_slot = ril_plugin_find_slot_imsi(plugin->slots,
|
||||
plugin->mms_imsi);
|
||||
}
|
||||
|
||||
if (mms_slot && mms_slot != slot) {
|
||||
/*
|
||||
* Reset default data SIM if another SIM is
|
||||
* temporarily selected for MMS.
|
||||
*/
|
||||
slot = NULL;
|
||||
}
|
||||
|
||||
/* Are we actually switching data SIMs? */
|
||||
old_data_slot = plugin->mms_slot ? plugin->mms_slot : plugin->data_slot;
|
||||
new_data_slot = mms_slot ? mms_slot : slot;
|
||||
|
||||
if (plugin->data_slot != slot) {
|
||||
mask |= RIL_PLUGIN_SIGNAL_DATA_PATH;
|
||||
if (plugin->data_slot) {
|
||||
/* Data no longer required for this slot */
|
||||
ril_data_allow(plugin->data_slot->data, FALSE);
|
||||
}
|
||||
plugin->data_slot = slot;
|
||||
if (slot) {
|
||||
DBG("Default data SIM at %s", slot->path);
|
||||
plugin->pub.default_data_path = slot->path;
|
||||
ril_data_allow(slot->data, TRUE);
|
||||
} else {
|
||||
DBG("No default data SIM");
|
||||
plugin->pub.default_data_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin->mms_slot != mms_slot) {
|
||||
mask |= RIL_PLUGIN_SIGNAL_MMS_PATH;
|
||||
plugin->mms_slot = mms_slot;
|
||||
if (mms_slot) {
|
||||
DBG("MMS data SIM at %s", mms_slot->path);
|
||||
plugin->pub.mms_path = mms_slot->path;
|
||||
} else {
|
||||
DBG("No MMS data SIM");
|
||||
plugin->pub.mms_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_data_slot != new_data_slot) {
|
||||
/* Yes we are switching data SIMs */
|
||||
if (old_data_slot) {
|
||||
ril_data_allow(old_data_slot->data, FALSE);
|
||||
}
|
||||
if (new_data_slot) {
|
||||
ril_data_allow(new_data_slot->data, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -400,22 +446,6 @@ static void ril_plugin_update_modem_paths_full(struct ril_plugin_priv *plugin)
|
||||
ril_plugin_update_modem_paths(plugin));
|
||||
}
|
||||
|
||||
static void ril_plugin_check_sim_state(struct ril_slot *slot)
|
||||
{
|
||||
const char *slot_imsi = ofono_sim_get_imsi(slot->sim);
|
||||
const char *dbus_imsi = ril_sim_dbus_imsi(slot->sim_dbus);
|
||||
|
||||
if (!slot_imsi) {
|
||||
if (slot->sim_dbus) {
|
||||
ril_sim_dbus_free(slot->sim_dbus);
|
||||
slot->sim_dbus = NULL;
|
||||
}
|
||||
} else if (g_strcmp0(slot_imsi, dbus_imsi)) {
|
||||
ril_sim_dbus_free(slot->sim_dbus);
|
||||
slot->sim_dbus = ril_sim_dbus_new(slot->modem);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
||||
{
|
||||
struct ril_slot *slot = data;
|
||||
@@ -455,11 +485,42 @@ static void ril_plugin_sim_state_watch(enum ofono_sim_state new_state,
|
||||
void *data)
|
||||
{
|
||||
struct ril_slot *slot = data;
|
||||
struct ril_plugin_priv *plugin = slot->plugin;
|
||||
|
||||
DBG("%s sim state %d", slot->path + 1, new_state);
|
||||
slot->sim_state = new_state;
|
||||
ril_plugin_check_sim_state(slot);
|
||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||
if (new_state == OFONO_SIM_STATE_READY) {
|
||||
struct ril_slot *voice_slot = plugin->voice_slot;
|
||||
struct ril_slot *data_slot = plugin->data_slot;
|
||||
int signal_mask;
|
||||
|
||||
/*
|
||||
* OFONO_SIM_STATE_READY means that pin code has been
|
||||
* entered (if necessary) and IMSI has been obtained.
|
||||
*
|
||||
* We want the first slot to be selected by default.
|
||||
* However, things may become available in pretty much
|
||||
* any order, so reset the slot pointers to NULL and let
|
||||
* ril_plugin_update_modem_paths() to pick them again.
|
||||
*
|
||||
* Only affects the very first boot and first boot after
|
||||
* the default voice SIM has been removed.
|
||||
*/
|
||||
plugin->voice_slot = NULL;
|
||||
plugin->data_slot = NULL;
|
||||
signal_mask = ril_plugin_update_modem_paths(plugin);
|
||||
if (voice_slot != plugin->voice_slot) {
|
||||
DBG("Voice slot changed");
|
||||
signal_mask |= RIL_PLUGIN_SIGNAL_VOICE_PATH;
|
||||
}
|
||||
if (data_slot != plugin->data_slot) {
|
||||
DBG("Data slot changed");
|
||||
signal_mask |= RIL_PLUGIN_SIGNAL_DATA_PATH;
|
||||
}
|
||||
ril_plugin_dbus_signal(plugin->dbus, signal_mask);
|
||||
} else {
|
||||
ril_plugin_update_modem_paths_full(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_plugin_register_sim(struct ril_slot *slot, struct ofono_sim *sim)
|
||||
@@ -468,11 +529,13 @@ static void ril_plugin_register_sim(struct ril_slot *slot, struct ofono_sim *sim
|
||||
GASSERT(!slot->sim);
|
||||
GASSERT(slot->sim_watch_id);
|
||||
GASSERT(!slot->sim_state_watch_id);
|
||||
|
||||
slot->sim = sim;
|
||||
slot->sim_state = ofono_sim_get_state(sim);
|
||||
slot->sim_state_watch_id = ofono_sim_add_state_watch(sim,
|
||||
ril_plugin_sim_state_watch, slot,
|
||||
ril_plugin_sim_state_watch_done);
|
||||
ril_sim_info_set_ofono_sim(slot->sim_info, sim);
|
||||
}
|
||||
|
||||
static void ril_plugin_sim_watch(struct ofono_atom *atom,
|
||||
@@ -485,10 +548,10 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
|
||||
ril_plugin_register_sim(slot, __ofono_atom_get_data(atom));
|
||||
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
|
||||
DBG("%s sim unregistered", slot->path + 1);
|
||||
ril_sim_info_set_ofono_sim(slot->sim_info, NULL);
|
||||
slot->sim = NULL;
|
||||
}
|
||||
|
||||
ril_plugin_check_sim_state(slot);
|
||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||
}
|
||||
|
||||
@@ -510,6 +573,19 @@ static void ril_plugin_slot_disconnected(GRilIoChannel *io, void *data)
|
||||
ril_plugin_handle_error((struct ril_slot *)data);
|
||||
}
|
||||
|
||||
static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
|
||||
void *data)
|
||||
{
|
||||
struct ril_slot *slot = data;
|
||||
|
||||
DBG("%s %d", slot->path + 1, online);
|
||||
GASSERT(slot->modem);
|
||||
GASSERT(slot->modem == modem);
|
||||
|
||||
slot->online = online;
|
||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||
}
|
||||
|
||||
static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
|
||||
{
|
||||
struct ril_slot *slot = data;
|
||||
@@ -518,14 +594,16 @@ static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
|
||||
GASSERT(slot->modem);
|
||||
GASSERT(slot->modem == modem);
|
||||
|
||||
if (slot->sim_dbus) {
|
||||
ril_sim_dbus_free(slot->sim_dbus);
|
||||
slot->sim_dbus = NULL;
|
||||
if (slot->sim_info_dbus) {
|
||||
ril_sim_info_dbus_free(slot->sim_info_dbus);
|
||||
slot->sim_info_dbus = NULL;
|
||||
}
|
||||
|
||||
slot->modem = NULL;
|
||||
slot->online = FALSE;
|
||||
ril_data_allow(slot->data, FALSE);
|
||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||
ril_sim_info_set_ofono_sim(slot->sim_info, NULL);
|
||||
}
|
||||
|
||||
static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
||||
@@ -629,7 +707,11 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
|
||||
ril_plugin_register_sim(slot, sim);
|
||||
}
|
||||
|
||||
slot->sim_info_dbus = ril_sim_info_dbus_new(slot->modem,
|
||||
slot->sim_info);
|
||||
|
||||
ril_modem_set_removed_cb(modem, ril_plugin_modem_removed, slot);
|
||||
ril_modem_set_online_cb(modem, ril_plugin_modem_online, slot);
|
||||
} else {
|
||||
ril_plugin_shutdown_slot(slot, TRUE);
|
||||
}
|
||||
@@ -728,7 +810,8 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
||||
slot->sim_card, ril_plugin_sim_state_changed, slot);
|
||||
|
||||
GASSERT(!slot->data);
|
||||
slot->data = ril_data_new(slot->plugin->data_manager, slot->io);
|
||||
slot->data = ril_data_new(slot->plugin->data_manager, slot->radio,
|
||||
slot->network, slot->io);
|
||||
|
||||
if (ril_plugin_multisim(slot->plugin)) {
|
||||
ril_data_set_name(slot->data, slot->path + 1);
|
||||
@@ -792,7 +875,8 @@ static gboolean ril_plugin_retry_init_io_cb(gpointer data)
|
||||
GASSERT(slot->retry_id);
|
||||
slot->retry_id = 0;
|
||||
ril_plugin_init_io(slot);
|
||||
return FALSE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_plugin_retry_init_io(struct ril_slot *slot)
|
||||
@@ -946,6 +1030,7 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
static void ril_plugin_delete_slot(struct ril_slot *slot)
|
||||
{
|
||||
ril_plugin_shutdown_slot(slot, TRUE);
|
||||
ril_sim_info_unref(slot->sim_info);
|
||||
g_free(slot->path);
|
||||
g_free(slot->imei);
|
||||
g_free(slot->name);
|
||||
@@ -1221,6 +1306,39 @@ void ril_plugin_set_default_data_imsi(struct ril_plugin *pub, const char *imsi)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean ril_plugin_set_mms_imsi(struct ril_plugin *pub, const char *imsi)
|
||||
{
|
||||
struct ril_plugin_priv *plugin = ril_plugin_cast(pub);
|
||||
|
||||
if (imsi && imsi[0]) {
|
||||
if (g_strcmp0(plugin->mms_imsi, imsi)) {
|
||||
if (ril_plugin_find_slot_imsi(plugin->slots, imsi)) {
|
||||
DBG("MMS sim %s", imsi);
|
||||
g_free(plugin->mms_imsi);
|
||||
pub->mms_imsi = plugin->mms_imsi =
|
||||
g_strdup(imsi);
|
||||
ril_plugin_dbus_signal(plugin->dbus,
|
||||
RIL_PLUGIN_SIGNAL_MMS_IMSI |
|
||||
ril_plugin_update_modem_paths(plugin));
|
||||
} else {
|
||||
DBG("IMSI not found: %s", imsi);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (plugin->mms_imsi) {
|
||||
DBG("No MMS sim");
|
||||
g_free(plugin->mms_imsi);
|
||||
pub->mms_imsi = plugin->mms_imsi = NULL;
|
||||
ril_plugin_dbus_signal(plugin->dbus,
|
||||
RIL_PLUGIN_SIGNAL_MMS_IMSI |
|
||||
ril_plugin_update_modem_paths(plugin));
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ril_plugin_init_slots(struct ril_plugin_priv *plugin)
|
||||
{
|
||||
int i;
|
||||
@@ -1237,6 +1355,7 @@ static void ril_plugin_init_slots(struct ril_plugin_priv *plugin)
|
||||
slot->plugin = plugin;
|
||||
slot->pub.path = slot->path;
|
||||
slot->pub.config = &slot->config;
|
||||
slot->sim_info = ril_sim_info_new(NULL);
|
||||
}
|
||||
|
||||
*info = NULL;
|
||||
@@ -1397,6 +1516,7 @@ static void ril_plugin_exit(void)
|
||||
g_free(ril_plugin->slots_info);
|
||||
g_free(ril_plugin->default_voice_imsi);
|
||||
g_free(ril_plugin->default_data_imsi);
|
||||
g_free(ril_plugin->mms_imsi);
|
||||
g_free(ril_plugin);
|
||||
ril_plugin = NULL;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ struct ril_slot_info {
|
||||
};
|
||||
|
||||
struct ril_plugin {
|
||||
const char *mms_imsi;
|
||||
const char *mms_path;
|
||||
const char *default_voice_imsi;
|
||||
const char *default_data_imsi;
|
||||
const char *default_voice_path;
|
||||
@@ -81,12 +83,17 @@ struct ril_modem {
|
||||
#define RIL_PLUGIN_SIGNAL_VOICE_IMSI (0x01)
|
||||
#define RIL_PLUGIN_SIGNAL_DATA_IMSI (0x02)
|
||||
#define RIL_PLUGIN_SIGNAL_VOICE_PATH (0x04)
|
||||
#define RIL_PLUGIN_SIGNAL_DATA_PATH (0x10)
|
||||
#define RIL_PLUGIN_SIGNAL_ENABLED_SLOTS (0x20)
|
||||
#define RIL_PLUGIN_SIGNAL_DATA_PATH (0x08)
|
||||
#define RIL_PLUGIN_SIGNAL_ENABLED_SLOTS (0x10)
|
||||
#define RIL_PLUGIN_SIGNAL_MMS_IMSI (0x20)
|
||||
#define RIL_PLUGIN_SIGNAL_MMS_PATH (0x40)
|
||||
|
||||
typedef void (*ril_modem_cb_t)(struct ril_modem *modem, void *data);
|
||||
typedef void (*ril_modem_online_cb_t)(struct ril_modem *modem, gboolean online,
|
||||
void *data);
|
||||
|
||||
void ril_plugin_set_enabled_slots(struct ril_plugin *plugin, char **slots);
|
||||
gboolean ril_plugin_set_mms_imsi(struct ril_plugin *plugin, const char *imsi);
|
||||
void ril_plugin_set_default_voice_imsi(struct ril_plugin *plugin,
|
||||
const char *imsi);
|
||||
void ril_plugin_set_default_data_imsi(struct ril_plugin *plugin,
|
||||
@@ -96,6 +103,11 @@ struct ril_sim_dbus *ril_sim_dbus_new(struct ril_modem *modem);
|
||||
const char *ril_sim_dbus_imsi(struct ril_sim_dbus *dbus);
|
||||
void ril_sim_dbus_free(struct ril_sim_dbus *dbus);
|
||||
|
||||
struct ril_sim_info_dbus;
|
||||
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
struct ril_sim_info *info);
|
||||
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus);
|
||||
|
||||
struct ril_plugin_dbus *ril_plugin_dbus_new(struct ril_plugin *plugin);
|
||||
void ril_plugin_dbus_free(struct ril_plugin_dbus *dbus);
|
||||
void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
|
||||
@@ -115,6 +127,8 @@ struct ofono_gprs *ril_modem_ofono_gprs(struct ril_modem *modem);
|
||||
struct ofono_netreg *ril_modem_ofono_netreg(struct ril_modem *modem);
|
||||
void ril_modem_set_removed_cb(struct ril_modem *modem, ril_modem_cb_t cb,
|
||||
void *data);
|
||||
void ril_modem_set_online_cb(struct ril_modem *modem, ril_modem_online_cb_t cb,
|
||||
void *data);
|
||||
|
||||
#define ril_modem_get_path(modem) ofono_modem_get_path((modem)->ofono)
|
||||
#define ril_modem_4g_enabled(modem) ((modem)->config.enable_4g)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -41,18 +41,21 @@ struct ril_plugin_dbus {
|
||||
DBusConnection *conn;
|
||||
gboolean block_imei_req;
|
||||
GSList *blocked_imei_req;
|
||||
guint mms_watch;
|
||||
};
|
||||
|
||||
#define RIL_DBUS_PATH "/"
|
||||
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
|
||||
#define RIL_DBUS_INTERFACE_VERSION (3)
|
||||
#define RIL_DBUS_INTERFACE_VERSION (4)
|
||||
|
||||
#define RIL_DBUS_ENABLED_MODEMS_CHANGED_SIGNAL "EnabledModemsChanged"
|
||||
#define RIL_DBUS_PRESENT_SIMS_CHANGED_SIGNAL "PresentSimsChanged"
|
||||
#define RIL_DBUS_DEFAULT_VOICE_SIM_CHANGED_SIGNAL "DefaultVoiceSimChanged"
|
||||
#define RIL_DBUS_DEFAULT_DATA_SIM_CHANGED_SIGNAL "DefaultDataSimChanged"
|
||||
#define RIL_DBUS_DEFAULT_VOICE_MODEM_CHANGED_SIGNAL "DefaultVoiceModemChanged"
|
||||
#define RIL_DBUS_DEFAULT_DATA_MODEM_CHANGED_SIGNAL "DefaultDataModemChanged"
|
||||
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
|
||||
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
|
||||
#define RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED "DefaultVoiceSimChanged"
|
||||
#define RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED "DefaultDataSimChanged"
|
||||
#define RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED "DefaultVoiceModemChanged"
|
||||
#define RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED "DefaultDataModemChanged"
|
||||
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
|
||||
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
|
||||
#define RIL_DBUS_IMSI_AUTO "auto"
|
||||
|
||||
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
|
||||
@@ -130,6 +133,12 @@ static void ril_plugin_dbus_append_boolean_array(DBusMessageIter *it,
|
||||
dbus_message_iter_close_container(it, &array);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_string(DBusMessageIter *it, const char *str)
|
||||
{
|
||||
if (!str) str = "";
|
||||
dbus_message_iter_append_basic(it, DBUS_TYPE_STRING, &str);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_imsi(DBusMessageIter *it, const char *imsi)
|
||||
{
|
||||
if (!imsi) imsi = RIL_DBUS_IMSI_AUTO;
|
||||
@@ -170,12 +179,12 @@ static inline void ril_plugin_dbus_signal_imsi(struct ril_plugin_dbus *dbus,
|
||||
name, DBUS_TYPE_STRING, &imsi, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static inline void ril_plugin_dbus_signal_path(struct ril_plugin_dbus *dbus,
|
||||
const char *name, const char *path)
|
||||
static inline void ril_plugin_dbus_signal_string(struct ril_plugin_dbus *dbus,
|
||||
const char *name, const char *str)
|
||||
{
|
||||
if (!path) path = "";
|
||||
if (!str) str = "";
|
||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
||||
name, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID);
|
||||
name, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask)
|
||||
@@ -183,29 +192,39 @@ void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask)
|
||||
if (dbus) {
|
||||
if (mask & RIL_PLUGIN_SIGNAL_VOICE_IMSI) {
|
||||
ril_plugin_dbus_signal_imsi(dbus,
|
||||
RIL_DBUS_DEFAULT_VOICE_SIM_CHANGED_SIGNAL,
|
||||
RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED,
|
||||
dbus->plugin->default_voice_imsi);
|
||||
}
|
||||
if (mask & RIL_PLUGIN_SIGNAL_DATA_IMSI) {
|
||||
ril_plugin_dbus_signal_imsi(dbus,
|
||||
RIL_DBUS_DEFAULT_DATA_SIM_CHANGED_SIGNAL,
|
||||
RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED,
|
||||
dbus->plugin->default_data_imsi);
|
||||
}
|
||||
if (mask & RIL_PLUGIN_SIGNAL_MMS_IMSI) {
|
||||
ril_plugin_dbus_signal_string(dbus,
|
||||
RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
|
||||
dbus->plugin->mms_imsi);
|
||||
}
|
||||
if (mask & RIL_PLUGIN_SIGNAL_ENABLED_SLOTS) {
|
||||
ril_plugin_dbus_signal_path_array(dbus,
|
||||
RIL_DBUS_ENABLED_MODEMS_CHANGED_SIGNAL,
|
||||
RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
|
||||
ril_plugin_dbus_enabled);
|
||||
}
|
||||
if (mask & RIL_PLUGIN_SIGNAL_VOICE_PATH) {
|
||||
ril_plugin_dbus_signal_path(dbus,
|
||||
RIL_DBUS_DEFAULT_VOICE_MODEM_CHANGED_SIGNAL,
|
||||
ril_plugin_dbus_signal_string(dbus,
|
||||
RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
|
||||
dbus->plugin->default_voice_path);
|
||||
}
|
||||
if (mask & RIL_PLUGIN_SIGNAL_DATA_PATH) {
|
||||
ril_plugin_dbus_signal_path(dbus,
|
||||
RIL_DBUS_DEFAULT_DATA_MODEM_CHANGED_SIGNAL,
|
||||
ril_plugin_dbus_signal_string(dbus,
|
||||
RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
|
||||
dbus->plugin->default_data_path);
|
||||
}
|
||||
if (mask & RIL_PLUGIN_SIGNAL_MMS_PATH) {
|
||||
ril_plugin_dbus_signal_string(dbus,
|
||||
RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
||||
dbus->plugin->mms_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +233,7 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
|
||||
{
|
||||
dbus_bool_t value = present;
|
||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
||||
RIL_DBUS_PRESENT_SIMS_CHANGED_SIGNAL,
|
||||
RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
|
||||
DBUS_TYPE_INT32, &index,
|
||||
DBUS_TYPE_BOOLEAN, &value,
|
||||
DBUS_TYPE_INVALID);
|
||||
@@ -323,6 +342,14 @@ static void ril_plugin_dbus_append_all3(DBusMessageIter *it,
|
||||
ril_plugin_dbus_append_string_array(it, dbus, ril_plugin_dbus_imei);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_append_all4(DBusMessageIter *it,
|
||||
struct ril_plugin_dbus *dbus)
|
||||
{
|
||||
ril_plugin_dbus_append_all3(it, dbus);
|
||||
ril_plugin_dbus_append_string(it, dbus->plugin->mms_imsi);
|
||||
ril_plugin_dbus_append_path(it, dbus->plugin->mms_path);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -344,6 +371,13 @@ static DBusMessage *ril_plugin_dbus_get_all3(DBusConnection *conn,
|
||||
ril_plugin_dbus_append_all3);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_all4(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
|
||||
ril_plugin_dbus_append_all4);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -391,6 +425,17 @@ static DBusMessage *ril_plugin_dbus_get_imei(DBusConnection *conn,
|
||||
ril_plugin_dbus_append_imei_array);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_reply_with_string(DBusMessage *msg,
|
||||
const char *str)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
ril_plugin_dbus_append_string(&iter, str);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_reply_with_imsi(DBusMessage *msg,
|
||||
const char *imsi)
|
||||
{
|
||||
@@ -420,6 +465,14 @@ static DBusMessage *ril_plugin_dbus_get_default_voice_sim(DBusConnection *conn,
|
||||
dbus->plugin->default_voice_imsi);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_mms_sim(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_plugin_dbus *dbus = data;
|
||||
|
||||
return ril_plugin_dbus_reply_with_string(msg, dbus->plugin->mms_imsi);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_reply_with_path(DBusMessage *msg,
|
||||
const char *path)
|
||||
{
|
||||
@@ -449,6 +502,14 @@ static DBusMessage *ril_plugin_dbus_get_default_voice_modem(DBusConnection *conn
|
||||
dbus->plugin->default_voice_path);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_get_mms_modem(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_plugin_dbus *dbus = data;
|
||||
|
||||
return ril_plugin_dbus_reply_with_path(msg, dbus->plugin->mms_path);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -519,37 +580,111 @@ static DBusMessage *ril_plugin_dbus_set_default_data_sim(DBusConnection *conn,
|
||||
ril_plugin_set_default_data_imsi);
|
||||
}
|
||||
|
||||
static void ril_plugin_dbus_mms_disconnect(DBusConnection *conn, void *data)
|
||||
{
|
||||
struct ril_plugin_dbus *dbus = data;
|
||||
|
||||
dbus->mms_watch = 0;
|
||||
if (dbus->plugin->mms_imsi) {
|
||||
DBG("MMS client is gone");
|
||||
ril_plugin_set_mms_imsi(dbus->plugin, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
struct ril_plugin_dbus *dbus = data;
|
||||
|
||||
GASSERT(conn == dbus->conn);
|
||||
dbus_message_iter_init(msg, &iter);
|
||||
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
|
||||
DBusBasicValue value;
|
||||
const char *imsi;
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &value);
|
||||
imsi = value.str;
|
||||
|
||||
/*
|
||||
* MMS IMSI is not persistent and has to be eventually
|
||||
* reset by the client or cleaned up if the client
|
||||
* unexpectedly disappears.
|
||||
*/
|
||||
if (ril_plugin_set_mms_imsi(dbus->plugin, imsi)) {
|
||||
|
||||
/*
|
||||
* Clear the previous MMS owner
|
||||
*/
|
||||
if (dbus->mms_watch) {
|
||||
g_dbus_remove_watch(dbus->conn, dbus->mms_watch);
|
||||
dbus->mms_watch = 0;
|
||||
}
|
||||
|
||||
if (dbus->plugin->mms_imsi &&
|
||||
dbus->plugin->mms_imsi[0]) {
|
||||
/*
|
||||
* This client becomes the owner
|
||||
*/
|
||||
DBG("Owner: %s", dbus_message_get_sender(msg));
|
||||
dbus->mms_watch =
|
||||
g_dbus_add_disconnect_watch(dbus->conn,
|
||||
dbus_message_get_sender(msg),
|
||||
ril_plugin_dbus_mms_disconnect,
|
||||
dbus, NULL);
|
||||
}
|
||||
|
||||
return ril_plugin_dbus_reply_with_string(msg,
|
||||
dbus->plugin->mms_path);
|
||||
} else {
|
||||
return __ofono_error_not_available(msg);
|
||||
}
|
||||
} else {
|
||||
return __ofono_error_invalid_args(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The client can call GetInterfaceVersion followed by the appropriate
|
||||
* GetAllx call to get all settings in two steps. Alternatively, it can
|
||||
* call GetAll followed by GetAllx based on the interface version returned
|
||||
* by GetAll. In either case, two D-Bus calls are required, unless the
|
||||
* client is willing to make the assumption about the ofono version it's
|
||||
* talking to.
|
||||
*/
|
||||
|
||||
#define RIL_DBUS_GET_ALL_ARGS \
|
||||
{"version", "i" }, \
|
||||
{"availableModems", "ao" }, \
|
||||
{"enabledModems", "ao" }, \
|
||||
{"defaultDataSim", "s" }, \
|
||||
{"defaultVoiceSim", "s" }, \
|
||||
{"defaultDataModem", "s" }, \
|
||||
{"defaultVoiceModem" , "s"}
|
||||
#define RIL_DBUS_GET_ALL2_ARGS \
|
||||
RIL_DBUS_GET_ALL_ARGS, \
|
||||
{"presentSims" , "ab"}
|
||||
#define RIL_DBUS_GET_ALL3_ARGS \
|
||||
RIL_DBUS_GET_ALL2_ARGS, \
|
||||
{"imei" , "as"}
|
||||
#define RIL_DBUS_GET_ALL4_ARGS \
|
||||
RIL_DBUS_GET_ALL3_ARGS, \
|
||||
{"mmsSim", "s" }, \
|
||||
{"mmsModem" , "s"}
|
||||
|
||||
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("GetAll", NULL,
|
||||
GDBUS_ARGS({"version", "i" },
|
||||
{"availableModems", "ao" },
|
||||
{"enabledModems", "ao" },
|
||||
{"defaultDataSim", "s" },
|
||||
{"defaultVoiceSim", "s" },
|
||||
{"defaultDataModem", "s" },
|
||||
{"defaultVoiceModem" , "s"}),
|
||||
{ GDBUS_METHOD("GetAll",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
|
||||
ril_plugin_dbus_get_all) },
|
||||
{ GDBUS_METHOD("GetAll2", NULL,
|
||||
GDBUS_ARGS({"version", "i" },
|
||||
{"availableModems", "ao" },
|
||||
{"enabledModems", "ao" },
|
||||
{"defaultDataSim", "s" },
|
||||
{"defaultVoiceSim", "s" },
|
||||
{"defaultDataModem", "s" },
|
||||
{"defaultVoiceModem" , "s"},
|
||||
{"presentSims" , "ab"}),
|
||||
{ GDBUS_METHOD("GetAll2",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL2_ARGS),
|
||||
ril_plugin_dbus_get_all2) },
|
||||
{ GDBUS_ASYNC_METHOD("GetAll3", NULL,
|
||||
GDBUS_ARGS({"version", "i" },
|
||||
{"availableModems", "ao" },
|
||||
{"enabledModems", "ao" },
|
||||
{"defaultDataSim", "s" },
|
||||
{"defaultVoiceSim", "s" },
|
||||
{"defaultDataModem", "s" },
|
||||
{"defaultVoiceModem" , "s"},
|
||||
{"presentSims" , "ab"},
|
||||
{"imei" , "as"}),
|
||||
{ GDBUS_ASYNC_METHOD("GetAll3",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL3_ARGS),
|
||||
ril_plugin_dbus_get_all3) },
|
||||
{ GDBUS_ASYNC_METHOD("GetAll4",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL4_ARGS),
|
||||
ril_plugin_dbus_get_all4) },
|
||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||
ril_plugin_dbus_get_interface_version) },
|
||||
@@ -571,12 +706,18 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("GetDefaultVoiceSim",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
ril_plugin_dbus_get_default_voice_sim) },
|
||||
{ GDBUS_METHOD("GetMmsSim",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
ril_plugin_dbus_get_mms_sim) },
|
||||
{ GDBUS_METHOD("GetDefaultDataModem",
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
ril_plugin_dbus_get_default_data_modem) },
|
||||
{ GDBUS_METHOD("GetDefaultVoiceModem",
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
ril_plugin_dbus_get_default_voice_modem) },
|
||||
{ GDBUS_METHOD("GetMmsModem",
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
ril_plugin_dbus_get_mms_modem) },
|
||||
{ GDBUS_METHOD("SetEnabledModems",
|
||||
GDBUS_ARGS({ "modems", "ao" }), NULL,
|
||||
ril_plugin_dbus_set_enabled_modems) },
|
||||
@@ -586,22 +727,29 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("SetDefaultVoiceSim",
|
||||
GDBUS_ARGS({ "imsi", "s" }), NULL,
|
||||
ril_plugin_dbus_set_default_voice_sim) },
|
||||
{ GDBUS_METHOD("SetMmsSim",
|
||||
GDBUS_ARGS({ "imsi", "s" }), NULL,
|
||||
ril_plugin_dbus_set_mms_sim) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const GDBusSignalTable ril_plugin_dbus_signals[] = {
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_ENABLED_MODEMS_CHANGED_SIGNAL,
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
|
||||
GDBUS_ARGS({ "modems", "ao" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_PRESENT_SIMS_CHANGED_SIGNAL,
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
|
||||
GDBUS_ARGS({"index", "i" },
|
||||
{"present" , "b"})) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_DEFAULT_DATA_SIM_CHANGED_SIGNAL,
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED,
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_DEFAULT_VOICE_SIM_CHANGED_SIGNAL,
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED,
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_DEFAULT_DATA_MODEM_CHANGED_SIGNAL,
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
|
||||
GDBUS_ARGS({ "path", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_DEFAULT_VOICE_MODEM_CHANGED_SIGNAL,
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
|
||||
GDBUS_ARGS({ "path", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
||||
GDBUS_ARGS({ "path", "s" })) },
|
||||
{ }
|
||||
};
|
||||
@@ -626,6 +774,10 @@ struct ril_plugin_dbus *ril_plugin_dbus_new(struct ril_plugin *plugin)
|
||||
void ril_plugin_dbus_free(struct ril_plugin_dbus *dbus)
|
||||
{
|
||||
if (dbus) {
|
||||
if (dbus->mms_watch) {
|
||||
g_dbus_remove_watch(dbus->conn, dbus->mms_watch);
|
||||
}
|
||||
|
||||
g_slist_free_full(dbus->blocked_imei_req,
|
||||
ril_plugin_dbus_cancel_request);
|
||||
g_dbus_unregister_interface(dbus->conn, RIL_DBUS_PATH,
|
||||
|
||||
@@ -89,7 +89,8 @@ static gboolean ril_radio_power_request_retry_cb(gpointer user_data)
|
||||
GASSERT(priv->retry_id);
|
||||
priv->retry_id = 0;
|
||||
ril_radio_submit_power_request(self, ril_radio_power_should_be_on(self));
|
||||
return FALSE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_radio_cancel_retry(struct ril_radio *self)
|
||||
@@ -228,12 +229,15 @@ void ril_radio_power_on(struct ril_radio *self, gpointer tag)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
struct ril_radio_priv *priv = self->priv;
|
||||
const gboolean was_on = ril_radio_power_should_be_on(self);
|
||||
|
||||
DBG("%s%p", priv->log_prefix, tag);
|
||||
g_hash_table_insert(priv->req_table, tag, tag);
|
||||
if (!was_on) {
|
||||
ril_radio_power_request(self, TRUE, FALSE);
|
||||
if (!g_hash_table_contains(priv->req_table, tag)) {
|
||||
gboolean was_on = ril_radio_power_should_be_on(self);
|
||||
|
||||
DBG("%s%p", priv->log_prefix, tag);
|
||||
g_hash_table_insert(priv->req_table, tag, tag);
|
||||
if (!was_on) {
|
||||
ril_radio_power_request(self, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,11 +247,12 @@ void ril_radio_power_off(struct ril_radio *self, gpointer tag)
|
||||
if (G_LIKELY(self)) {
|
||||
struct ril_radio_priv *priv = self->priv;
|
||||
|
||||
DBG("%s%p", priv->log_prefix, tag);
|
||||
if (g_hash_table_remove(priv->req_table, tag) &&
|
||||
!ril_radio_power_should_be_on(self)) {
|
||||
/* The last one turns the lights off */
|
||||
ril_radio_power_request(self, FALSE, FALSE);
|
||||
if (g_hash_table_remove(priv->req_table, tag)) {
|
||||
DBG("%s%p", priv->log_prefix, tag);
|
||||
if (!ril_radio_power_should_be_on(self)) {
|
||||
/* The last one turns the lights off */
|
||||
ril_radio_power_request(self, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ gulong ril_radio_add_state_changed_handler(struct ril_radio *radio,
|
||||
void ril_radio_remove_handler(struct ril_radio *radio, gulong id);
|
||||
enum ril_radio_state ril_radio_state_parse(const void *data, guint len);
|
||||
|
||||
#endif /* RIL_RADIO */
|
||||
#endif /* RIL_RADIO_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
@@ -141,6 +141,7 @@ static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
|
||||
|
||||
static struct ril_sim_pin_cbd *ril_sim_pin_cbd_new(struct ril_sim *sd,
|
||||
enum ofono_sim_password_type passwd_type,
|
||||
gboolean state_change_expected,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim_pin_cbd *cbd = g_new0(struct ril_sim_pin_cbd, 1);
|
||||
@@ -150,8 +151,11 @@ static struct ril_sim_pin_cbd *ril_sim_pin_cbd_new(struct ril_sim *sd,
|
||||
cbd->data = data;
|
||||
cbd->passwd_type = passwd_type;
|
||||
cbd->card = ril_sim_card_ref(sd->card);
|
||||
cbd->card_status_id = ril_sim_card_add_status_received_handler(sd->card,
|
||||
if (state_change_expected) {
|
||||
cbd->card_status_id =
|
||||
ril_sim_card_add_status_received_handler(sd->card,
|
||||
ril_sim_pin_cbd_state_event_count_cb, cbd);
|
||||
}
|
||||
return cbd;
|
||||
}
|
||||
|
||||
@@ -752,7 +756,8 @@ static gboolean ril_sim_query_passwd_state_timeout_cb(gpointer user_data)
|
||||
GASSERT(sd->query_passwd_state_cb);
|
||||
sd->query_passwd_state_timeout_id = 0;
|
||||
ril_sim_finish_passwd_state_query(sd, OFONO_SIM_PASSWORD_INVALID);
|
||||
return FALSE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_sim_query_passwd_state(struct ofono_sim *sim,
|
||||
@@ -795,7 +800,8 @@ static gboolean ril_sim_pin_change_state_timeout_cb(gpointer user_data)
|
||||
sd->pin_cbd_list = g_list_remove(sd->pin_cbd_list, cbd);
|
||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||
ril_sim_pin_cbd_free(cbd);
|
||||
return FALSE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_sim_pin_change_state_status_cb(struct ril_sim_card *sc,
|
||||
@@ -841,7 +847,8 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
||||
ril_status, cbd->passwd_type, retry_count);
|
||||
|
||||
cbd->ril_status = ril_status;
|
||||
if (!cbd->state_event_count || ril_sim_app_in_transient_state(sd)) {
|
||||
if (cbd->card_status_id && (!cbd->state_event_count ||
|
||||
ril_sim_app_in_transient_state(sd))) {
|
||||
|
||||
GASSERT(!g_list_find(sd->pin_cbd_list, cbd));
|
||||
GASSERT(!cbd->timeout_id);
|
||||
@@ -862,7 +869,7 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
||||
} else {
|
||||
struct ofono_error error;
|
||||
|
||||
/* Looks like the state has already changed */
|
||||
/* It's either already changed or not expected at all */
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
cbd->cb(ril_error_ok(&error), cbd->data);
|
||||
} else {
|
||||
@@ -884,7 +891,8 @@ static void ril_sim_pin_send(struct ofono_sim *sim, const char *passwd,
|
||||
DBG("%s,aid=%s", passwd, ril_sim_app_id(sd));
|
||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PIN,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PIN, cb, data));
|
||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PIN,
|
||||
TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
@@ -917,7 +925,7 @@ static guint ril_perso_change_state(struct ofono_sim *sim,
|
||||
if (req) {
|
||||
id = grilio_queue_send_request_full(sd->q, req, code,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, passwd_type, cb, data));
|
||||
ril_sim_pin_cbd_new(sd, passwd_type, TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
@@ -979,7 +987,7 @@ static void ril_sim_pin_change_state(struct ofono_sim *sim,
|
||||
id = grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_SET_FACILITY_LOCK,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, passwd_type, cb, data));
|
||||
ril_sim_pin_cbd_new(sd, passwd_type, TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
@@ -1003,7 +1011,8 @@ static void ril_sim_pin_send_puk(struct ofono_sim *sim,
|
||||
DBG("puk=%s,pin=%s,aid=%s", puk, passwd, ril_sim_app_id(sd));
|
||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PUK,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PUK, cb, data));
|
||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PUK,
|
||||
TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
@@ -1025,7 +1034,8 @@ static void ril_sim_change_passwd(struct ofono_sim *sim,
|
||||
(passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2) ?
|
||||
RIL_REQUEST_CHANGE_SIM_PIN2 : RIL_REQUEST_CHANGE_SIM_PIN,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, passwd_type, cb, data));
|
||||
ril_sim_pin_cbd_new(sd, passwd_type, FALSE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
|
||||
static gboolean ril_sim_register(gpointer user)
|
||||
|
||||
@@ -66,7 +66,7 @@ gulong ril_sim_card_add_app_changed_handler(struct ril_sim_card *sc,
|
||||
void ril_sim_card_remove_handler(struct ril_sim_card *sc, gulong id);
|
||||
|
||||
/* Inline wrappers */
|
||||
G_INLINE_FUNC enum ril_app_type
|
||||
static inline enum ril_app_type
|
||||
ril_sim_card_app_type(struct ril_sim_card *sc)
|
||||
{ return (sc && sc->app) ? sc->app->app_type : RIL_APPTYPE_UNKNOWN; }
|
||||
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <ofono/dbus.h>
|
||||
|
||||
#include <gdbus.h>
|
||||
|
||||
#include "ofono.h"
|
||||
#include "storage.h"
|
||||
|
||||
struct ril_sim_dbus {
|
||||
char *path;
|
||||
char *imsi;
|
||||
char *name;
|
||||
char *default_name;
|
||||
gboolean enable_4g;
|
||||
GKeyFile *storage;
|
||||
DBusConnection *conn;
|
||||
struct ril_modem *md;
|
||||
};
|
||||
|
||||
#define RIL_SIM_STORE "ril"
|
||||
#define RIL_SIM_STORE_GROUP "Settings"
|
||||
#define RIL_SIM_STORE_ENABLE_4G "Enable4G"
|
||||
#define RIL_SIM_STORE_DISPLAY_NAME "DisplayName"
|
||||
|
||||
#define RIL_SIM_DBUS_INTERFACE "org.nemomobile.ofono.SimSettings"
|
||||
#define RIL_SIM_DBUS_INTERFACE_VERSION (1)
|
||||
|
||||
#define RIL_SIM_DBUS_DISPLAY_NAME_CHANGED_SIGNAL "DisplayNameChanged"
|
||||
#define RIL_SIM_DBUS_ENABLE_4G_CHANGED_SIGNAL "Enable4GChanged"
|
||||
|
||||
static DBusMessage *ril_sim_dbus_get_all(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_dbus *dbus = data;
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
dbus_int32_t version = RIL_SIM_DBUS_INTERFACE_VERSION;
|
||||
dbus_bool_t enable_4g = dbus->enable_4g;
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &enable_4g);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &dbus->name);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_dbus_get_interface_version(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
dbus_int32_t version = RIL_SIM_DBUS_INTERFACE_VERSION;
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_dbus_get_enable_4g(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_dbus *dbus = data;
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
dbus_bool_t enable_4g = dbus->enable_4g;
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &enable_4g);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_dbus_get_display_name(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_dbus *dbus = data;
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &dbus->name);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static void ril_sim_dbus_update_display_name(struct ril_sim_dbus *dbus,
|
||||
const char *name)
|
||||
{
|
||||
if (g_strcmp0(dbus->name, name)) {
|
||||
g_free(dbus->name);
|
||||
dbus->name = g_strdup(name);
|
||||
g_key_file_set_string(dbus->storage, RIL_SIM_STORE_GROUP,
|
||||
RIL_SIM_STORE_DISPLAY_NAME, name);
|
||||
storage_sync(dbus->imsi, RIL_SIM_STORE, dbus->storage);
|
||||
g_dbus_emit_signal(dbus->conn, dbus->path,
|
||||
RIL_SIM_DBUS_INTERFACE,
|
||||
RIL_SIM_DBUS_DISPLAY_NAME_CHANGED_SIGNAL,
|
||||
DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_dbus_set_display_name(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init(msg, &iter);
|
||||
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
|
||||
struct ril_sim_dbus *dbus = data;
|
||||
DBusBasicValue value;
|
||||
const char *name;
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &value);
|
||||
name = value.str;
|
||||
if (!name || !name[0]) name = dbus->default_name;
|
||||
ril_sim_dbus_update_display_name(dbus, name);
|
||||
return dbus_message_new_method_return(msg);
|
||||
} else {
|
||||
return __ofono_error_invalid_args(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static const GDBusMethodTable ril_sim_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("GetAll",
|
||||
NULL, GDBUS_ARGS({ "settings", "ibs" }),
|
||||
ril_sim_dbus_get_all) },
|
||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||
ril_sim_dbus_get_interface_version) },
|
||||
{ GDBUS_METHOD("GetEnable4G",
|
||||
NULL, GDBUS_ARGS({ "enable", "b" }),
|
||||
ril_sim_dbus_get_enable_4g) },
|
||||
{ GDBUS_METHOD("GetDisplayName",
|
||||
NULL, GDBUS_ARGS({ "name", "s" }),
|
||||
ril_sim_dbus_get_display_name) },
|
||||
{ GDBUS_METHOD("SetDisplayName",
|
||||
GDBUS_ARGS({ "name", "s" }), NULL,
|
||||
ril_sim_dbus_set_display_name) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const GDBusSignalTable ril_sim_dbus_signals[] = {
|
||||
{ GDBUS_SIGNAL(RIL_SIM_DBUS_DISPLAY_NAME_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "name", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_SIM_DBUS_ENABLE_4G_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "enabled", "b" })) },
|
||||
{ }
|
||||
};
|
||||
|
||||
const char *ril_sim_dbus_imsi(struct ril_sim_dbus *dbus)
|
||||
{
|
||||
return dbus ? dbus->imsi : NULL;
|
||||
}
|
||||
|
||||
struct ril_sim_dbus *ril_sim_dbus_new(struct ril_modem *md)
|
||||
{
|
||||
const char *imsi = ofono_sim_get_imsi(ril_modem_ofono_sim(md));
|
||||
|
||||
if (imsi) {
|
||||
GError *error = NULL;
|
||||
const struct ril_slot_config *config = &md->config;
|
||||
struct ril_sim_dbus *dbus = g_new0(struct ril_sim_dbus, 1);
|
||||
|
||||
DBG("%s", ril_modem_get_path(md));
|
||||
dbus->md = md;
|
||||
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||
dbus->path = g_strdup(ril_modem_get_path(md));
|
||||
dbus->imsi = g_strdup(imsi);
|
||||
dbus->default_name = g_strdup(config->default_name);
|
||||
|
||||
/* Load settings */
|
||||
dbus->storage = storage_open(imsi, RIL_SIM_STORE);
|
||||
dbus->enable_4g = g_key_file_get_boolean(dbus->storage,
|
||||
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_ENABLE_4G, &error);
|
||||
if (error) {
|
||||
dbus->enable_4g = config->enable_4g;
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
}
|
||||
dbus->name = g_key_file_get_string(dbus->storage,
|
||||
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_DISPLAY_NAME, NULL);
|
||||
if (!dbus->name) {
|
||||
dbus->name = g_strdup(config->default_name);
|
||||
GASSERT(dbus->name);
|
||||
}
|
||||
|
||||
/* Register D-Bus interface */
|
||||
if (g_dbus_register_interface(dbus->conn, dbus->path,
|
||||
RIL_SIM_DBUS_INTERFACE, ril_sim_dbus_methods,
|
||||
ril_sim_dbus_signals, NULL, dbus, NULL)) {
|
||||
ofono_modem_add_interface(md->ofono,
|
||||
RIL_SIM_DBUS_INTERFACE);
|
||||
return dbus;
|
||||
} else {
|
||||
ofono_error("RIL D-Bus register failed");
|
||||
ril_sim_dbus_free(dbus);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ril_sim_dbus_free(struct ril_sim_dbus *dbus)
|
||||
{
|
||||
if (dbus) {
|
||||
DBG("%s", dbus->path);
|
||||
g_dbus_unregister_interface(dbus->conn, dbus->path,
|
||||
RIL_SIM_DBUS_INTERFACE);
|
||||
ofono_modem_remove_interface(dbus->md->ofono,
|
||||
RIL_SIM_DBUS_INTERFACE);
|
||||
dbus_connection_unref(dbus->conn);
|
||||
g_key_file_free(dbus->storage);
|
||||
g_free(dbus->path);
|
||||
g_free(dbus->imsi);
|
||||
g_free(dbus->name);
|
||||
g_free(dbus->default_name);
|
||||
g_free(dbus);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
460
ofono/drivers/ril/ril_sim_info.c
Normal file
460
ofono/drivers/ril/ril_sim_info.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "ril_sim_info.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <ofono/sim.h>
|
||||
|
||||
#include "ofono.h"
|
||||
#include "storage.h"
|
||||
|
||||
#define RIL_SIM_INFO_STORE "cache"
|
||||
#define RIL_SIM_INFO_STORE_GROUP "sim"
|
||||
#define RIL_SIM_INFO_STORE_SPN "spn"
|
||||
|
||||
/* ICCID -> IMSI map */
|
||||
#define RIL_SIM_ICCID_MAP "iccidmap"
|
||||
#define RIL_SIM_ICCID_MAP_IMSI "imsi"
|
||||
|
||||
typedef GObjectClass RilSimInfoClass;
|
||||
typedef struct ril_sim_info RilSimInfo;
|
||||
|
||||
typedef void (*ril_sim_info_remove_cb_t)(struct ofono_sim *sim, unsigned int id);
|
||||
typedef void (*ril_sim_info_set_value_cb_t)(struct ril_sim_info *info,
|
||||
const char *value);
|
||||
|
||||
struct ril_sim_info_watch {
|
||||
ril_sim_info_set_value_cb_t set_value;
|
||||
ril_sim_info_remove_cb_t remove;
|
||||
struct ril_sim_info *info;
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
struct ril_sim_info_priv {
|
||||
char *iccid;
|
||||
char *imsi;
|
||||
char *spn;
|
||||
struct ofono_sim *sim;
|
||||
struct ril_sim_info_watch state_watch;
|
||||
struct ril_sim_info_watch iccid_watch;
|
||||
struct ril_sim_info_watch imsi_watch;
|
||||
struct ril_sim_info_watch spn_watch;
|
||||
gboolean update_imsi_cache;
|
||||
gboolean update_iccid_map;
|
||||
};
|
||||
|
||||
enum ril_sim_info_signal {
|
||||
SIGNAL_ICCID_CHANGED,
|
||||
SIGNAL_IMSI_CHANGED,
|
||||
SIGNAL_SPN_CHANGED,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
#define SIGNAL_ICCID_CHANGED_NAME "ril-sim-info-iccid-changed"
|
||||
#define SIGNAL_IMSI_CHANGED_NAME "ril-sim-info-imsi-changed"
|
||||
#define SIGNAL_SPN_CHANGED_NAME "ril-sim-info-spn-changed"
|
||||
|
||||
static guint ril_sim_info_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE(RilSimInfo, ril_sim_info, G_TYPE_OBJECT)
|
||||
#define RIL_SIMINFO_TYPE (ril_sim_info_get_type())
|
||||
#define RIL_SIMINFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||
RIL_SIMINFO_TYPE, RilSimInfo))
|
||||
|
||||
#define NEW_SIGNAL(klass,name) \
|
||||
ril_sim_info_signals[SIGNAL_##name##_CHANGED] = \
|
||||
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
||||
|
||||
static void ril_sim_info_signal_emit(struct ril_sim_info *self,
|
||||
enum ril_sim_info_signal id)
|
||||
{
|
||||
g_signal_emit(self, ril_sim_info_signals[id], 0);
|
||||
}
|
||||
|
||||
static void ril_sim_info_watch_remove(struct ril_sim_info_watch *watch)
|
||||
{
|
||||
if (watch->id) {
|
||||
struct ril_sim_info_priv *priv = watch->info->priv;
|
||||
|
||||
GASSERT(priv->sim);
|
||||
if (priv->sim) {
|
||||
watch->remove(priv->sim, watch->id);
|
||||
GASSERT(!watch->id);
|
||||
}
|
||||
|
||||
watch->id = 0;
|
||||
}
|
||||
|
||||
if (watch->set_value) {
|
||||
watch->set_value(watch->info, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_remove_spn_watch(struct ofono_sim *sim, unsigned int id)
|
||||
{
|
||||
ofono_sim_remove_spn_watch(sim, &id);
|
||||
}
|
||||
|
||||
static void ril_sim_info_update_imsi_cache(struct ril_sim_info *self)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (priv->update_imsi_cache && priv->imsi && priv->imsi[0] &&
|
||||
priv->spn && priv->spn[0]) {
|
||||
const char *store = RIL_SIM_INFO_STORE;
|
||||
GKeyFile *cache = storage_open(priv->imsi, store);
|
||||
|
||||
DBG("Updating " STORAGEDIR "/%s/%s", priv->imsi, store);
|
||||
g_key_file_set_string(cache, RIL_SIM_INFO_STORE_GROUP,
|
||||
RIL_SIM_INFO_STORE_SPN, priv->spn);
|
||||
storage_close(priv->imsi, store, cache, TRUE);
|
||||
priv->update_imsi_cache = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_update_iccid_map(struct ril_sim_info *self)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (priv->update_iccid_map && priv->iccid && priv->iccid[0] &&
|
||||
priv->imsi && priv->imsi[0]) {
|
||||
const char *store = RIL_SIM_ICCID_MAP;
|
||||
GKeyFile *map = storage_open(NULL, store);
|
||||
|
||||
DBG("Updating " STORAGEDIR "/%s", store);
|
||||
g_key_file_set_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||
priv->iccid, priv->imsi);
|
||||
storage_close(NULL, store, map, TRUE);
|
||||
priv->update_iccid_map = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_set_imsi(struct ril_sim_info *self, const char *imsi)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (g_strcmp0(priv->imsi, imsi)) {
|
||||
g_free(priv->imsi);
|
||||
self->imsi = priv->imsi = g_strdup(imsi);
|
||||
priv->update_iccid_map = TRUE;
|
||||
ril_sim_info_update_iccid_map(self);
|
||||
ril_sim_info_update_imsi_cache(self);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_set_spn(struct ril_sim_info *self, const char *spn)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (g_strcmp0(priv->spn, spn)) {
|
||||
g_free(priv->spn);
|
||||
self->spn = priv->spn = g_strdup(spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
ril_sim_info_update_imsi_cache(self);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_load_cache(struct ril_sim_info *self)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (priv->iccid && priv->iccid[0]) {
|
||||
GKeyFile *map = storage_open(NULL, RIL_SIM_ICCID_MAP);
|
||||
char *imsi = g_key_file_get_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||
priv->iccid, NULL);
|
||||
g_key_file_free(map);
|
||||
|
||||
if (imsi && imsi[0] && g_strcmp0(priv->imsi, imsi)) {
|
||||
if (priv->imsi && priv->imsi[0]) {
|
||||
/* Need to update ICCID -> IMSI map */
|
||||
DBG("IMSI changed %s -> %s", priv->imsi, imsi);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
}
|
||||
g_free(priv->imsi);
|
||||
self->imsi = priv->imsi = imsi;
|
||||
DBG("imsi[%s] = %s", priv->iccid, imsi);
|
||||
ril_sim_info_update_iccid_map(self);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||
} else if (imsi) {
|
||||
g_free(imsi);
|
||||
} else {
|
||||
DBG("No imsi for iccid %s", priv->iccid);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->imsi && priv->imsi[0]) {
|
||||
GKeyFile *cache = storage_open(priv->imsi, RIL_SIM_INFO_STORE);
|
||||
char *spn = g_key_file_get_string(cache,
|
||||
RIL_SIM_INFO_STORE_GROUP,
|
||||
RIL_SIM_INFO_STORE_SPN, NULL);
|
||||
g_key_file_free(cache);
|
||||
|
||||
if (spn && spn[0] && g_strcmp0(priv->spn, spn)) {
|
||||
if (priv->spn && priv->spn[0]) {
|
||||
/* Need to update the cache file */
|
||||
DBG("spn changing %s -> %s", priv->spn, spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
}
|
||||
g_free(priv->spn);
|
||||
self->spn = priv->spn = spn;
|
||||
DBG("spn[%s] = \"%s\"", priv->imsi, spn);
|
||||
ril_sim_info_update_imsi_cache(self);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
||||
} else if (spn) {
|
||||
g_free(spn);
|
||||
} else {
|
||||
DBG("No spn for imsi %s", priv->imsi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_set_iccid(struct ril_sim_info *self, const char *iccid)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (g_strcmp0(priv->iccid, iccid)) {
|
||||
g_free(priv->iccid);
|
||||
self->iccid = priv->iccid = g_strdup(iccid);
|
||||
ril_sim_info_signal_emit(self, SIGNAL_ICCID_CHANGED);
|
||||
if (iccid) {
|
||||
ril_sim_info_load_cache(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_imsi_watch_cb(const char *imsi, void *data)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
DBG("%s", imsi);
|
||||
ril_sim_info_set_imsi(watch->info, imsi);
|
||||
}
|
||||
|
||||
static void ril_sim_info_spn_watch_cb(const char *spn, const char *dc,
|
||||
void *data)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
DBG("%s", spn);
|
||||
ril_sim_info_set_spn(watch->info, spn);
|
||||
}
|
||||
|
||||
static void ril_sim_info_iccid_watch_cb(const char *iccid, void *data)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
DBG("%s", iccid);
|
||||
ril_sim_info_set_iccid(watch->info, iccid);
|
||||
}
|
||||
|
||||
static void ril_sim_info_watch_done(void *data)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
|
||||
GASSERT(watch->id);
|
||||
watch->id = 0;
|
||||
}
|
||||
|
||||
static void ril_sim_info_handle_sim_state(struct ril_sim_info *self,
|
||||
enum ofono_sim_state state)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
struct ril_sim_info_watch *watch;
|
||||
|
||||
DBG("%d", state);
|
||||
|
||||
switch (state) {
|
||||
case OFONO_SIM_STATE_READY:
|
||||
/* SPN */
|
||||
watch = &priv->spn_watch;
|
||||
if (!watch->id) {
|
||||
ofono_sim_add_spn_watch(priv->sim, &watch->id,
|
||||
ril_sim_info_spn_watch_cb, watch,
|
||||
ril_sim_info_watch_done);
|
||||
GASSERT(priv->spn_watch.id);
|
||||
}
|
||||
/* IMSI */
|
||||
watch = &priv->imsi_watch;
|
||||
if (!watch->id) {
|
||||
watch->id = ofono_sim_add_imsi_watch(priv->sim,
|
||||
ril_sim_info_imsi_watch_cb, watch,
|
||||
ril_sim_info_watch_done);
|
||||
GASSERT(watch->id);
|
||||
}
|
||||
/* no break */
|
||||
case OFONO_SIM_STATE_INSERTED:
|
||||
case OFONO_SIM_STATE_LOCKED_OUT:
|
||||
/* ICCID */
|
||||
watch = &priv->iccid_watch;
|
||||
if (!watch->id) {
|
||||
watch->id = ofono_sim_add_iccid_watch(priv->sim,
|
||||
ril_sim_info_iccid_watch_cb, watch,
|
||||
ril_sim_info_watch_done);
|
||||
GASSERT(watch->id);
|
||||
}
|
||||
break;
|
||||
case OFONO_SIM_STATE_NOT_PRESENT:
|
||||
case OFONO_SIM_STATE_RESETTING:
|
||||
ril_sim_info_watch_remove(&priv->spn_watch);
|
||||
ril_sim_info_watch_remove(&priv->imsi_watch);
|
||||
ril_sim_info_watch_remove(&priv->iccid_watch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_state_watch_cb(enum ofono_sim_state new_state,
|
||||
void *data)
|
||||
{
|
||||
struct ril_sim_info_watch *watch = data;
|
||||
ril_sim_info_handle_sim_state(watch->info, new_state);
|
||||
}
|
||||
|
||||
struct ril_sim_info *ril_sim_info_new(struct ofono_sim *sim)
|
||||
{
|
||||
struct ril_sim_info *self = g_object_new(RIL_SIMINFO_TYPE, NULL);
|
||||
|
||||
ril_sim_info_set_ofono_sim(self, sim);
|
||||
return self;
|
||||
}
|
||||
|
||||
struct ril_sim_info *ril_sim_info_ref(struct ril_sim_info *self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_ref(RIL_SIMINFO(self));
|
||||
return self;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ril_sim_info_unref(struct ril_sim_info *self)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
g_object_unref(RIL_SIMINFO(self));
|
||||
}
|
||||
}
|
||||
|
||||
void ril_sim_info_set_ofono_sim(struct ril_sim_info *self, struct ofono_sim *sim)
|
||||
{
|
||||
if (G_LIKELY(self)) {
|
||||
struct ril_sim_info_priv *priv = self->priv;
|
||||
|
||||
if (priv->sim != sim) {
|
||||
ril_sim_info_watch_remove(&priv->state_watch);
|
||||
ril_sim_info_watch_remove(&priv->iccid_watch);
|
||||
ril_sim_info_watch_remove(&priv->imsi_watch);
|
||||
ril_sim_info_watch_remove(&priv->spn_watch);
|
||||
|
||||
priv->update_imsi_cache = FALSE;
|
||||
priv->update_iccid_map = FALSE;
|
||||
priv->sim = sim;
|
||||
|
||||
if (sim) {
|
||||
priv->state_watch.id =
|
||||
ofono_sim_add_state_watch(sim,
|
||||
ril_sim_info_state_watch_cb,
|
||||
&priv->state_watch,
|
||||
ril_sim_info_watch_done);
|
||||
GASSERT(priv->state_watch.id);
|
||||
DBG("Attached to sim");
|
||||
ril_sim_info_handle_sim_state(self,
|
||||
ofono_sim_get_state(sim));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gulong ril_sim_info_add_iccid_changed_handler(struct ril_sim_info *self,
|
||||
ril_sim_info_cb_t cb, void *arg)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||
SIGNAL_ICCID_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||
}
|
||||
|
||||
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *self,
|
||||
ril_sim_info_cb_t cb, void *arg)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||
SIGNAL_IMSI_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||
}
|
||||
|
||||
gulong ril_sim_info_add_spn_changed_handler(struct ril_sim_info *self,
|
||||
ril_sim_info_cb_t cb, void *arg)
|
||||
{
|
||||
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||
SIGNAL_SPN_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||
}
|
||||
|
||||
void ril_sim_info_remove_handler(struct ril_sim_info *self, gulong id)
|
||||
{
|
||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||
g_signal_handler_disconnect(self, id);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_info_watch_init(struct ril_sim_info *self,
|
||||
struct ril_sim_info_watch *watch,
|
||||
ril_sim_info_set_value_cb_t set_value,
|
||||
ril_sim_info_remove_cb_t remove)
|
||||
{
|
||||
watch->info = self;
|
||||
watch->set_value = set_value;
|
||||
watch->remove = remove;
|
||||
}
|
||||
|
||||
static void ril_sim_info_init(struct ril_sim_info *self)
|
||||
{
|
||||
struct ril_sim_info_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||
RIL_SIMINFO_TYPE, struct ril_sim_info_priv);
|
||||
|
||||
self->priv = priv;
|
||||
ril_sim_info_watch_init(self, &priv->state_watch, NULL,
|
||||
ofono_sim_remove_state_watch);
|
||||
ril_sim_info_watch_init(self, &priv->iccid_watch, ril_sim_info_set_iccid,
|
||||
ofono_sim_remove_iccid_watch);
|
||||
ril_sim_info_watch_init(self, &priv->imsi_watch, ril_sim_info_set_imsi,
|
||||
ofono_sim_remove_imsi_watch);
|
||||
ril_sim_info_watch_init(self, &priv->spn_watch, ril_sim_info_set_spn,
|
||||
ril_sim_info_remove_spn_watch);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dispose(GObject *object)
|
||||
{
|
||||
struct ril_sim_info *self = RIL_SIMINFO(object);
|
||||
|
||||
ril_sim_info_set_ofono_sim(self, NULL);
|
||||
G_OBJECT_CLASS(ril_sim_info_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void ril_sim_info_class_init(RilSimInfoClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = ril_sim_info_dispose;
|
||||
g_type_class_add_private(klass, sizeof(struct ril_sim_info_priv));
|
||||
NEW_SIGNAL(klass, ICCID);
|
||||
NEW_SIGNAL(klass, IMSI);
|
||||
NEW_SIGNAL(klass, SPN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
52
ofono/drivers/ril/ril_sim_info.h
Normal file
52
ofono/drivers/ril/ril_sim_info.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef RIL_SIM_INFO_H
|
||||
#define RIL_SIM_INFO_H
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
struct ril_sim_info {
|
||||
GObject object;
|
||||
struct ril_sim_info_priv *priv;
|
||||
const char *iccid;
|
||||
const char *imsi;
|
||||
const char *spn;
|
||||
};
|
||||
|
||||
struct ofono_sim;
|
||||
typedef void (*ril_sim_info_cb_t)(struct ril_sim_info *info, void *arg);
|
||||
|
||||
struct ril_sim_info *ril_sim_info_new(struct ofono_sim *sim);
|
||||
struct ril_sim_info *ril_sim_info_ref(struct ril_sim_info *info);
|
||||
void ril_sim_info_unref(struct ril_sim_info *si);
|
||||
void ril_sim_info_set_ofono_sim(struct ril_sim_info *si, struct ofono_sim *sim);
|
||||
gulong ril_sim_info_add_iccid_changed_handler(struct ril_sim_info *si,
|
||||
ril_sim_info_cb_t cb, void *arg);
|
||||
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *si,
|
||||
ril_sim_info_cb_t cb, void *arg);
|
||||
gulong ril_sim_info_add_spn_changed_handler(struct ril_sim_info *si,
|
||||
ril_sim_info_cb_t cb, void *arg);
|
||||
void ril_sim_info_remove_handler(struct ril_sim_info *si, gulong id);
|
||||
|
||||
#endif /* RIL_SIM_INFO_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
243
ofono/drivers/ril/ril_sim_info_dbus.c
Normal file
243
ofono/drivers/ril/ril_sim_info_dbus.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_sim_info.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <ofono/dbus.h>
|
||||
|
||||
#include <gdbus.h>
|
||||
|
||||
#include "ofono.h"
|
||||
#include "storage.h"
|
||||
|
||||
enum sim_info_event_id {
|
||||
SIM_INFO_EVENT_ICCID,
|
||||
SIM_INFO_EVENT_IMSI,
|
||||
SIM_INFO_EVENT_SPN,
|
||||
SIM_INFO_EVENT_COUNT
|
||||
};
|
||||
|
||||
struct ril_sim_info_dbus {
|
||||
struct ril_modem *md;
|
||||
struct ril_sim_info *info;
|
||||
DBusConnection *conn;
|
||||
char *path;
|
||||
gulong handler_id[SIM_INFO_EVENT_COUNT];
|
||||
};
|
||||
|
||||
#define RIL_SIM_INFO_DBUS_INTERFACE "org.nemomobile.ofono.SimInfo"
|
||||
#define RIL_SIM_INFO_DBUS_INTERFACE_VERSION (1)
|
||||
|
||||
#define RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL "CardIdentifierChanged"
|
||||
#define RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL "SubscriberIdentityChanged"
|
||||
#define RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL "ServiceProviderNameChanged"
|
||||
|
||||
static void ril_sim_info_dbus_append_string(DBusMessageIter *it, const char *s)
|
||||
{
|
||||
if (!s) s = "";
|
||||
dbus_message_iter_append_basic(it, DBUS_TYPE_STRING, &s);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_info_dbus_reply_with_string(DBusMessage *msg,
|
||||
const char *str)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
ril_sim_info_dbus_append_string(&iter, str);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_info_dbus_get_all(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = data;
|
||||
struct ril_sim_info *info = dbus->info;
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
const dbus_int32_t version = RIL_SIM_INFO_DBUS_INTERFACE_VERSION;
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
||||
ril_sim_info_dbus_append_string(&iter, info->iccid);
|
||||
ril_sim_info_dbus_append_string(&iter, info->imsi);
|
||||
ril_sim_info_dbus_append_string(&iter, info->spn);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_info_dbus_get_version(DBusConnection *dc,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||
dbus_int32_t version = RIL_SIM_INFO_DBUS_INTERFACE_VERSION;
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_info_dbus_get_iccid(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = data;
|
||||
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->iccid);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_info_dbus_get_imsi(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = data;
|
||||
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->imsi);
|
||||
}
|
||||
|
||||
static DBusMessage *ril_sim_info_dbus_get_spn(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = data;
|
||||
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->spn);
|
||||
}
|
||||
|
||||
static const GDBusMethodTable ril_sim_info_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("GetAll",
|
||||
NULL, GDBUS_ARGS({"version", "i" },
|
||||
{"iccid", "s" },
|
||||
{"imsi", "s" },
|
||||
{"spn" , "s"}),
|
||||
ril_sim_info_dbus_get_all) },
|
||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||
ril_sim_info_dbus_get_version) },
|
||||
{ GDBUS_METHOD("GetCardIdentifier",
|
||||
NULL, GDBUS_ARGS({ "iccid", "s" }),
|
||||
ril_sim_info_dbus_get_iccid) },
|
||||
{ GDBUS_METHOD("GetSubscriberIdentity",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
ril_sim_info_dbus_get_imsi) },
|
||||
{ GDBUS_METHOD("GetServiceProviderName",
|
||||
NULL, GDBUS_ARGS({ "spn", "s" }),
|
||||
ril_sim_info_dbus_get_spn) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const GDBusSignalTable ril_sim_info_dbus_signals[] = {
|
||||
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "iccid", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "spn", "s" })) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void ril_sim_info_dbus_emit(struct ril_sim_info_dbus *dbus,
|
||||
const char *signal, const char *value)
|
||||
{
|
||||
const char *arg = value;
|
||||
if (!arg) arg = "";
|
||||
g_dbus_emit_signal(dbus->conn, dbus->path, RIL_SIM_INFO_DBUS_INTERFACE,
|
||||
signal, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dbus_iccid_cb(struct ril_sim_info *info, void *arg)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = arg;
|
||||
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
|
||||
info->iccid);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dbus_imsi_cb(struct ril_sim_info *info, void *arg)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = arg;
|
||||
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
|
||||
info->imsi);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dbus_spn_cb(struct ril_sim_info *info, void *arg)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = arg;
|
||||
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
|
||||
info->spn);
|
||||
}
|
||||
|
||||
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
struct ril_sim_info *info)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = g_new0(struct ril_sim_info_dbus, 1);
|
||||
|
||||
DBG("%s", ril_modem_get_path(md));
|
||||
dbus->md = md;
|
||||
dbus->path = g_strdup(ril_modem_get_path(md));
|
||||
dbus->info = ril_sim_info_ref(info);
|
||||
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||
|
||||
/* Register D-Bus interface */
|
||||
if (g_dbus_register_interface(dbus->conn, dbus->path,
|
||||
RIL_SIM_INFO_DBUS_INTERFACE, ril_sim_info_dbus_methods,
|
||||
ril_sim_info_dbus_signals, NULL, dbus, NULL)) {
|
||||
ofono_modem_add_interface(md->ofono,
|
||||
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||
|
||||
dbus->handler_id[SIM_INFO_EVENT_ICCID] =
|
||||
ril_sim_info_add_iccid_changed_handler(info,
|
||||
ril_sim_info_dbus_iccid_cb, dbus);
|
||||
dbus->handler_id[SIM_INFO_EVENT_IMSI] =
|
||||
ril_sim_info_add_imsi_changed_handler(info,
|
||||
ril_sim_info_dbus_imsi_cb, dbus);
|
||||
dbus->handler_id[SIM_INFO_EVENT_SPN] =
|
||||
ril_sim_info_add_spn_changed_handler(info,
|
||||
ril_sim_info_dbus_spn_cb, dbus);
|
||||
|
||||
return dbus;
|
||||
} else {
|
||||
ofono_error("RIL D-Bus register failed");
|
||||
ril_sim_info_dbus_free(dbus);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus)
|
||||
{
|
||||
if (dbus) {
|
||||
unsigned int i;
|
||||
|
||||
DBG("%s", dbus->path);
|
||||
g_dbus_unregister_interface(dbus->conn, dbus->path,
|
||||
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||
ofono_modem_remove_interface(dbus->md->ofono,
|
||||
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||
dbus_connection_unref(dbus->conn);
|
||||
|
||||
for (i=0; i<G_N_ELEMENTS(dbus->handler_id); i++) {
|
||||
ril_sim_info_remove_handler(dbus->info,
|
||||
dbus->handler_id[i]);
|
||||
}
|
||||
ril_sim_info_unref(dbus->info);
|
||||
|
||||
g_free(dbus->path);
|
||||
g_free(dbus);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -43,6 +43,7 @@ struct ril_modem;
|
||||
struct ril_radio;
|
||||
struct ril_network;
|
||||
struct ril_sim_card;
|
||||
struct ril_sim_info;
|
||||
struct ril_plugin_dbus;
|
||||
|
||||
#endif /* RIL_TYPES_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015 Jolla Ltd.
|
||||
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
@@ -101,11 +101,10 @@ static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
|
||||
}
|
||||
grilio_request_append_utf8_chars(req, (char*)
|
||||
unpacked_buf, length);
|
||||
grilio_queue_send_request_full(ud->q, req,
|
||||
RIL_REQUEST_SEND_USSD, ril_ussd_cb,
|
||||
ril_ussd_cbd_free,
|
||||
ril_ussd_cbd_new(cb, data));
|
||||
grilio_queue_send_request(ud->q, req,
|
||||
RIL_REQUEST_SEND_USSD);
|
||||
grilio_request_unref(req);
|
||||
cb(ril_error_ok(&error), data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,14 +58,6 @@ struct netreg_data {
|
||||
int corestatus; /* Registration status previously reported to core */
|
||||
};
|
||||
|
||||
/* 27.007 Section 7.3 <stat> */
|
||||
enum operator_status {
|
||||
OPERATOR_STATUS_UNKNOWN = 0,
|
||||
OPERATOR_STATUS_AVAILABLE = 1,
|
||||
OPERATOR_STATUS_CURRENT = 2,
|
||||
OPERATOR_STATUS_FORBIDDEN = 3,
|
||||
};
|
||||
|
||||
struct ofono_netreg *current_netreg;
|
||||
|
||||
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
|
||||
|
||||
@@ -215,6 +215,22 @@ ofono_bool_t ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
|
||||
|
||||
ofono_bool_t ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id);
|
||||
|
||||
typedef void (*ofono_sim_iccid_event_cb_t)(const char *iccid, void *data);
|
||||
|
||||
unsigned int ofono_sim_add_iccid_watch(struct ofono_sim *sim,
|
||||
ofono_sim_iccid_event_cb_t cb, void *data,
|
||||
ofono_destroy_func destroy);
|
||||
|
||||
void ofono_sim_remove_iccid_watch(struct ofono_sim *sim, unsigned int id);
|
||||
|
||||
typedef void (*ofono_sim_imsi_event_cb_t)(const char *imsi, void *data);
|
||||
|
||||
unsigned int ofono_sim_add_imsi_watch(struct ofono_sim *sim,
|
||||
ofono_sim_imsi_event_cb_t cb, void *data,
|
||||
ofono_destroy_func destroy);
|
||||
|
||||
void ofono_sim_remove_imsi_watch(struct ofono_sim *sim, unsigned int id);
|
||||
|
||||
void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted);
|
||||
|
||||
struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim);
|
||||
|
||||
@@ -57,8 +57,6 @@
|
||||
#define MAX_MESSAGE_CENTER_LENGTH 255
|
||||
#define MAX_CONTEXTS 256
|
||||
#define SUSPEND_TIMEOUT 8
|
||||
#define MAX_MMS_MTU 1280
|
||||
#define MAX_GPRS_MTU 1280
|
||||
|
||||
struct ofono_gprs {
|
||||
GSList *contexts;
|
||||
@@ -790,31 +788,6 @@ static void pri_reset_context_settings(struct pri_context *ctx)
|
||||
g_free(interface);
|
||||
}
|
||||
|
||||
static void pri_limit_mtu(const char *interface, int max_mtu)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int sk;
|
||||
|
||||
if (interface == NULL)
|
||||
return;
|
||||
|
||||
sk = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sk < 0)
|
||||
return;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, interface, IFNAMSIZ);
|
||||
|
||||
if (ioctl(sk, SIOCGIFMTU, &ifr) < 0 || ifr.ifr_mtu > max_mtu) {
|
||||
ifr.ifr_mtu = max_mtu;
|
||||
|
||||
if (ioctl(sk, SIOCSIFMTU, &ifr) < 0)
|
||||
ofono_error("Failed to set MTU");
|
||||
}
|
||||
|
||||
close(sk);
|
||||
}
|
||||
|
||||
static void pri_update_mms_context_settings(struct pri_context *ctx)
|
||||
{
|
||||
struct ofono_gprs_context *gc = ctx->context_driver;
|
||||
@@ -832,8 +805,6 @@ static void pri_update_mms_context_settings(struct pri_context *ctx)
|
||||
|
||||
if (ctx->proxy_host)
|
||||
pri_setproxy(settings->interface, ctx->proxy_host);
|
||||
|
||||
pri_limit_mtu(settings->interface, MAX_MMS_MTU);
|
||||
}
|
||||
|
||||
static gboolean pri_str_changed(const char *val, const char *newval)
|
||||
@@ -844,8 +815,6 @@ static gboolean pri_str_changed(const char *val, const char *newval)
|
||||
static gboolean pri_str_update(char *val, const char *newval,
|
||||
const int maxlen)
|
||||
{
|
||||
DBG("oldval: %s, newval: %s, mmaxlen: %d", val, newval, maxlen);
|
||||
|
||||
if (newval) {
|
||||
if (strcmp(val, newval)) {
|
||||
strncpy(val, newval, maxlen);
|
||||
@@ -1132,9 +1101,6 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
|
||||
|
||||
pri_context_signal_settings(ctx, gc->settings->ipv4 != NULL,
|
||||
gc->settings->ipv6 != NULL);
|
||||
|
||||
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET)
|
||||
pri_limit_mtu(gc->settings->interface, MAX_GPRS_MTU);
|
||||
}
|
||||
|
||||
value = ctx->active;
|
||||
|
||||
@@ -62,6 +62,8 @@ struct ofono_netreg {
|
||||
struct ofono_network_registration_ops *ops;
|
||||
int flags;
|
||||
DBusMessage *pending;
|
||||
GSList *pending_auto;
|
||||
GSList *pending_list;
|
||||
int signal_strength;
|
||||
struct sim_spdi *spdi;
|
||||
struct sim_eons *eons;
|
||||
@@ -599,7 +601,7 @@ static DBusMessage *network_operator_register(DBusConnection *conn,
|
||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||
return __ofono_error_access_denied(msg);
|
||||
|
||||
if (netreg->pending)
|
||||
if (netreg->pending || netreg->pending_auto || netreg->pending_list)
|
||||
return __ofono_error_busy(msg);
|
||||
|
||||
if (netreg->driver->register_manual == NULL)
|
||||
@@ -854,6 +856,44 @@ static DBusMessage *network_get_properties(DBusConnection *conn,
|
||||
return reply;
|
||||
}
|
||||
|
||||
static void network_reply_ok(gpointer data)
|
||||
{
|
||||
DBusMessage *msg = data;
|
||||
|
||||
__ofono_dbus_pending_reply(&msg, dbus_message_new_method_return(msg));
|
||||
}
|
||||
|
||||
static void network_reply_failed(gpointer data)
|
||||
{
|
||||
DBusMessage *msg = data;
|
||||
|
||||
__ofono_dbus_pending_reply(&msg, __ofono_error_failed(msg));
|
||||
}
|
||||
|
||||
static void network_reply_canceled(gpointer data)
|
||||
{
|
||||
DBusMessage *msg = data;
|
||||
|
||||
__ofono_dbus_pending_reply(&msg, __ofono_error_canceled(msg));
|
||||
}
|
||||
|
||||
static void register_auto_callback(const struct ofono_error *error, void *data)
|
||||
{
|
||||
struct ofono_netreg *netreg = data;
|
||||
|
||||
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
|
||||
g_slist_free_full(netreg->pending_auto, network_reply_ok);
|
||||
else
|
||||
g_slist_free_full(netreg->pending_auto, network_reply_failed);
|
||||
|
||||
netreg->pending_auto = NULL;
|
||||
|
||||
if (netreg->driver->registration_status)
|
||||
netreg->driver->registration_status(netreg,
|
||||
registration_status_callback,
|
||||
netreg);
|
||||
}
|
||||
|
||||
static DBusMessage *network_register(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -862,17 +902,19 @@ static DBusMessage *network_register(DBusConnection *conn,
|
||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||
return __ofono_error_access_denied(msg);
|
||||
|
||||
if (netreg->pending)
|
||||
if (netreg->pending || netreg->pending_list)
|
||||
return __ofono_error_busy(msg);
|
||||
|
||||
if (netreg->driver->register_auto == NULL)
|
||||
return __ofono_error_not_implemented(msg);
|
||||
|
||||
netreg->pending = dbus_message_ref(msg);
|
||||
|
||||
netreg->driver->register_auto(netreg, register_callback, netreg);
|
||||
|
||||
set_registration_mode(netreg, NETWORK_REGISTRATION_MODE_AUTO);
|
||||
netreg->pending_auto = g_slist_append(netreg->pending_auto,
|
||||
dbus_message_ref(msg));
|
||||
if (!netreg->pending_auto->next) {
|
||||
netreg->driver->register_auto(netreg, register_auto_callback,
|
||||
netreg);
|
||||
set_registration_mode(netreg, NETWORK_REGISTRATION_MODE_AUTO);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -972,26 +1014,15 @@ static void network_signal_operators_changed(struct ofono_netreg *netreg)
|
||||
g_dbus_send_message(conn, signal);
|
||||
}
|
||||
|
||||
static void operator_list_callback(const struct ofono_error *error, int total,
|
||||
const struct ofono_network_operator *list,
|
||||
void *data)
|
||||
static void operator_list_reply(gpointer data, gpointer user_data)
|
||||
{
|
||||
struct ofono_netreg *netreg = data;
|
||||
struct ofono_netreg *netreg = user_data;
|
||||
DBusMessage *msg = data;
|
||||
DBusMessage *reply;
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter array;
|
||||
gboolean changed;
|
||||
|
||||
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
DBG("Error occurred during operator list");
|
||||
__ofono_dbus_pending_reply(&netreg->pending,
|
||||
__ofono_error_failed(netreg->pending));
|
||||
return;
|
||||
}
|
||||
|
||||
changed = update_operator_list(netreg, total, list);
|
||||
|
||||
reply = dbus_message_new_method_return(netreg->pending);
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
|
||||
@@ -1008,12 +1039,31 @@ static void operator_list_callback(const struct ofono_error *error, int total,
|
||||
append_operator_struct_list(netreg, &array);
|
||||
dbus_message_iter_close_container(&iter, &array);
|
||||
|
||||
__ofono_dbus_pending_reply(&netreg->pending, reply);
|
||||
__ofono_dbus_pending_reply(&msg, reply);
|
||||
}
|
||||
|
||||
DBG("operator list %schanged", changed ? "" : "not ");
|
||||
static void operator_list_callback(const struct ofono_error *error, int total,
|
||||
const struct ofono_network_operator *list,
|
||||
void *data)
|
||||
{
|
||||
struct ofono_netreg *netreg = data;
|
||||
|
||||
if (changed)
|
||||
network_signal_operators_changed(netreg);
|
||||
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||
DBG("Error occurred during operator list");
|
||||
g_slist_free_full(netreg->pending_list, network_reply_failed);
|
||||
} else {
|
||||
gboolean changed = update_operator_list(netreg, total, list);
|
||||
|
||||
g_slist_foreach(netreg->pending_list, operator_list_reply,
|
||||
netreg);
|
||||
g_slist_free(netreg->pending_list);
|
||||
|
||||
DBG("operator list %schanged", changed ? "" : "not ");
|
||||
if (changed)
|
||||
network_signal_operators_changed(netreg);
|
||||
}
|
||||
|
||||
netreg->pending_list = NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *network_scan(DBusConnection *conn,
|
||||
@@ -1024,16 +1074,17 @@ static DBusMessage *network_scan(DBusConnection *conn,
|
||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||
return __ofono_error_access_denied(msg);
|
||||
|
||||
if (netreg->pending)
|
||||
if (netreg->pending || netreg->pending_auto)
|
||||
return __ofono_error_busy(msg);
|
||||
|
||||
if (netreg->driver->list_operators == NULL)
|
||||
return __ofono_error_not_implemented(msg);
|
||||
|
||||
netreg->pending = dbus_message_ref(msg);
|
||||
|
||||
netreg->driver->list_operators(netreg, operator_list_callback, netreg);
|
||||
|
||||
netreg->pending_list = g_slist_append(netreg->pending_list,
|
||||
dbus_message_ref(msg));
|
||||
if (!netreg->pending_list->next)
|
||||
netreg->driver->list_operators(netreg, operator_list_callback,
|
||||
netreg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1898,6 +1949,15 @@ static void netreg_remove(struct ofono_atom *atom)
|
||||
if (netreg->driver != NULL && netreg->driver->remove != NULL)
|
||||
netreg->driver->remove(netreg);
|
||||
|
||||
if (netreg->pending) {
|
||||
__ofono_dbus_pending_reply(&netreg->pending,
|
||||
__ofono_error_canceled(netreg->pending));
|
||||
} else if (netreg->pending_auto) {
|
||||
g_slist_free_full(netreg->pending_auto, network_reply_canceled);
|
||||
} else if (netreg->pending_list) {
|
||||
g_slist_free_full(netreg->pending_list, network_reply_canceled);
|
||||
}
|
||||
|
||||
sim_eons_free(netreg->eons);
|
||||
sim_spdi_free(netreg->spdi);
|
||||
|
||||
|
||||
115
ofono/src/sim.c
115
ofono/src/sim.c
@@ -53,6 +53,7 @@ struct ofono_sim {
|
||||
|
||||
/* Contents of the SIM file system, in rough initialization order */
|
||||
char *iccid;
|
||||
struct ofono_watchlist *iccid_watches;
|
||||
|
||||
char **language_prefs;
|
||||
unsigned char *efli;
|
||||
@@ -80,6 +81,7 @@ struct ofono_sim {
|
||||
char *imsi;
|
||||
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||
struct ofono_watchlist *imsi_watches;
|
||||
|
||||
GSList *own_numbers;
|
||||
GSList *new_numbers;
|
||||
@@ -340,6 +342,94 @@ static void call_state_watches(struct ofono_sim *sim)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int add_watch_item(struct ofono_watchlist *watchlist,
|
||||
void *notify, void *notify_data,
|
||||
ofono_destroy_func destroy)
|
||||
{
|
||||
struct ofono_watchlist_item *item;
|
||||
|
||||
item = g_new0(struct ofono_watchlist_item, 1);
|
||||
item->notify = notify;
|
||||
item->notify_data = notify_data;
|
||||
item->destroy = destroy;
|
||||
|
||||
return __ofono_watchlist_add_item(watchlist, item);
|
||||
}
|
||||
|
||||
static void iccid_watch_cb(gpointer data, gpointer user_data)
|
||||
{
|
||||
struct ofono_watchlist_item *item = data;
|
||||
struct ofono_sim *sim = user_data;
|
||||
ofono_sim_iccid_event_cb_t cb = item->notify;
|
||||
|
||||
cb(sim->iccid, item->notify_data);
|
||||
}
|
||||
|
||||
static inline void iccid_watches_notify(struct ofono_sim *sim)
|
||||
{
|
||||
g_slist_foreach(sim->iccid_watches->items, iccid_watch_cb, sim);
|
||||
}
|
||||
|
||||
unsigned int ofono_sim_add_iccid_watch(struct ofono_sim *sim,
|
||||
ofono_sim_iccid_event_cb_t cb, void *data,
|
||||
ofono_destroy_func destroy)
|
||||
{
|
||||
unsigned int watch_id;
|
||||
|
||||
DBG("%p", sim);
|
||||
if (sim == NULL)
|
||||
return 0;
|
||||
|
||||
watch_id = add_watch_item(sim->iccid_watches, cb, data, destroy);
|
||||
|
||||
if (sim->iccid)
|
||||
cb(sim->iccid, data);
|
||||
|
||||
return watch_id;
|
||||
}
|
||||
|
||||
void ofono_sim_remove_iccid_watch(struct ofono_sim *sim, unsigned int id)
|
||||
{
|
||||
__ofono_watchlist_remove_item(sim->iccid_watches, id);
|
||||
}
|
||||
|
||||
static void imsi_watch_cb(gpointer data, gpointer user_data)
|
||||
{
|
||||
struct ofono_watchlist_item *item = data;
|
||||
struct ofono_sim *sim = user_data;
|
||||
ofono_sim_imsi_event_cb_t cb = item->notify;
|
||||
|
||||
cb(sim->imsi, item->notify_data);
|
||||
}
|
||||
|
||||
static inline void imsi_watches_notify(struct ofono_sim *sim)
|
||||
{
|
||||
g_slist_foreach(sim->imsi_watches->items, imsi_watch_cb, sim);
|
||||
}
|
||||
|
||||
unsigned int ofono_sim_add_imsi_watch(struct ofono_sim *sim,
|
||||
ofono_sim_imsi_event_cb_t cb, void *data,
|
||||
ofono_destroy_func destroy)
|
||||
{
|
||||
unsigned int watch_id;
|
||||
|
||||
DBG("%p", sim);
|
||||
if (sim == NULL)
|
||||
return 0;
|
||||
|
||||
watch_id = add_watch_item(sim->imsi_watches, cb, data, destroy);
|
||||
|
||||
if (sim->imsi)
|
||||
cb(sim->imsi, data);
|
||||
|
||||
return watch_id;
|
||||
}
|
||||
|
||||
void ofono_sim_remove_imsi_watch(struct ofono_sim *sim, unsigned int id)
|
||||
{
|
||||
__ofono_watchlist_remove_item(sim->imsi_watches, id);
|
||||
}
|
||||
|
||||
static DBusMessage *sim_get_properties(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -380,6 +470,10 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
|
||||
ofono_dbus_dict_append(&dict, "SubscriberIdentity",
|
||||
DBUS_TYPE_STRING, &sim->imsi);
|
||||
|
||||
if (sim->spn)
|
||||
ofono_dbus_dict_append(&dict, "ServiceProviderName",
|
||||
DBUS_TYPE_STRING, &sim->spn);
|
||||
|
||||
fdn = sim->fixed_dialing;
|
||||
ofono_dbus_dict_append(&dict, "FixedDialing", DBUS_TYPE_BOOLEAN, &fdn);
|
||||
|
||||
@@ -1483,6 +1577,7 @@ static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
|
||||
DBUS_TYPE_STRING, &str);
|
||||
}
|
||||
|
||||
imsi_watches_notify(sim);
|
||||
sim_set_ready(sim);
|
||||
|
||||
}
|
||||
@@ -1856,6 +1951,7 @@ static void sim_initialize_after_pin(struct ofono_sim *sim)
|
||||
{
|
||||
sim->context = ofono_sim_context_create(sim);
|
||||
sim->spn_watches = __ofono_watchlist_new(g_free);
|
||||
sim->imsi_watches = __ofono_watchlist_new(g_free);
|
||||
|
||||
ofono_sim_read(sim->context, SIM_EFPHASE_FILEID,
|
||||
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
||||
@@ -2085,6 +2181,7 @@ static void sim_iccid_read_cb(int ok, int length, int record,
|
||||
"CardIdentifier",
|
||||
DBUS_TYPE_STRING,
|
||||
&sim->iccid);
|
||||
iccid_watches_notify(sim);
|
||||
}
|
||||
|
||||
static void sim_iccid_changed(int id, void *userdata)
|
||||
@@ -2467,6 +2564,11 @@ static void sim_free_main_state(struct ofono_sim *sim)
|
||||
|
||||
sim_spn_close(sim);
|
||||
|
||||
if (sim->imsi_watches) {
|
||||
__ofono_watchlist_free(sim->imsi_watches);
|
||||
sim->imsi_watches = NULL;
|
||||
}
|
||||
|
||||
if (sim->context) {
|
||||
ofono_sim_context_free(sim->context);
|
||||
sim->context = NULL;
|
||||
@@ -2570,6 +2672,9 @@ static inline void spn_watches_notify(struct ofono_sim *sim)
|
||||
static void sim_spn_set(struct ofono_sim *sim, const void *data, int length,
|
||||
const unsigned char *dc)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
const char *path = __ofono_atom_get_path(sim->atom);
|
||||
|
||||
g_free(sim->spn);
|
||||
sim->spn = NULL;
|
||||
|
||||
@@ -2611,6 +2716,12 @@ static void sim_spn_set(struct ofono_sim *sim, const void *data, int length,
|
||||
sim->spn_dc = g_memdup(dc, 1);
|
||||
|
||||
notify:
|
||||
if (sim->spn)
|
||||
ofono_dbus_signal_property_changed(conn, path,
|
||||
OFONO_SIM_MANAGER_INTERFACE,
|
||||
"ServiceProviderName",
|
||||
DBUS_TYPE_STRING, &sim->spn);
|
||||
|
||||
spn_watches_notify(sim);
|
||||
}
|
||||
|
||||
@@ -2885,6 +2996,9 @@ static void sim_unregister(struct ofono_atom *atom)
|
||||
|
||||
__ofono_modem_remove_atom_watch(modem, sim->hfp_watch);
|
||||
|
||||
__ofono_watchlist_free(sim->iccid_watches);
|
||||
sim->iccid_watches = NULL;
|
||||
|
||||
__ofono_watchlist_free(sim->state_watches);
|
||||
sim->state_watches = NULL;
|
||||
|
||||
@@ -3017,6 +3131,7 @@ void ofono_sim_register(struct ofono_sim *sim)
|
||||
|
||||
ofono_modem_add_interface(modem, OFONO_SIM_MANAGER_INTERFACE);
|
||||
sim->state_watches = __ofono_watchlist_new(g_free);
|
||||
sim->iccid_watches = __ofono_watchlist_new(g_free);
|
||||
sim->simfs = sim_fs_new(sim, sim->driver);
|
||||
|
||||
__ofono_atom_register(sim->atom, sim_unregister);
|
||||
|
||||
@@ -41,6 +41,9 @@ unsigned int __ofono_watchlist_add_item(struct ofono_watchlist *watchlist,
|
||||
{
|
||||
item->id = ++watchlist->next_id;
|
||||
|
||||
if (item->id == 0)
|
||||
item->id = ++watchlist->next_id;
|
||||
|
||||
watchlist->items = g_slist_prepend(watchlist->items, item);
|
||||
|
||||
return item->id;
|
||||
|
||||
Reference in New Issue
Block a user