mirror of
https://github.com/sailfishos/ofono
synced 2025-11-26 04:11: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_gprs_context.c \
|
||||||
drivers/ril/ril_mce.c \
|
drivers/ril/ril_mce.c \
|
||||||
drivers/ril/ril_modem.c \
|
drivers/ril/ril_modem.c \
|
||||||
|
drivers/ril/ril_mtu.c \
|
||||||
drivers/ril/ril_netreg.c \
|
drivers/ril/ril_netreg.c \
|
||||||
drivers/ril/ril_network.c \
|
drivers/ril/ril_network.c \
|
||||||
drivers/ril/ril_oem_raw.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_radio_settings.c \
|
||||||
drivers/ril/ril_sim.c \
|
drivers/ril/ril_sim.c \
|
||||||
drivers/ril/ril_sim_card.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_sms.c \
|
||||||
drivers/ril/ril_stk.c \
|
drivers/ril/ril_stk.c \
|
||||||
drivers/ril/ril_ussd.c \
|
drivers/ril/ril_ussd.c \
|
||||||
|
|||||||
@@ -93,6 +93,11 @@ Properties boolean Present [readonly]
|
|||||||
|
|
||||||
Contains the IMSI of the SIM, if available.
|
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]
|
string MobileCountryCode [readonly, optional]
|
||||||
|
|
||||||
Contains the Mobile Country Code (MCC) of the home
|
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_FACILITY_REJECTED 29
|
||||||
#define CALL_FAIL_NORMAL_UNSPECIFIED 31
|
#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_NO_REASON 0
|
||||||
#define RIL_DEACTIVATE_DATA_CALL_RADIO_SHUTDOWN 1
|
#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
|
enum ril_auth {
|
||||||
#define RIL_DATA_PROFILE_TETHERED 1
|
RIL_AUTH_NONE = 0,
|
||||||
#define RIL_DATA_PROFILE_IMS 2
|
RIL_AUTH_PAP = 1,
|
||||||
#define RIL_DATA_PROFILE_FOTA 3 /* FOTA = Firmware Over the Air */
|
RIL_AUTH_CHAP = 2,
|
||||||
#define RIL_DATA_PROFILE_CBS 4
|
RIL_AUTH_BOTH = 3
|
||||||
#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
|
|
||||||
|
|
||||||
#define RIL_CARD_MAX_APPS 8
|
#define RIL_CARD_MAX_APPS 8
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,24 +17,81 @@
|
|||||||
#define RIL_DATA_H
|
#define RIL_DATA_H
|
||||||
|
|
||||||
#include "ril_types.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;
|
||||||
struct ril_data_manager *ril_data_manager_new(void);
|
struct ril_data_manager *ril_data_manager_new(void);
|
||||||
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
|
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
|
||||||
void ril_data_manager_unref(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);
|
struct ril_data *ril_data_ref(struct ril_data *data);
|
||||||
void ril_data_unref(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_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);
|
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,
|
gulong ril_data_add_allow_changed_handler(struct ril_data *data,
|
||||||
ril_data_cb_t cb, void *arg);
|
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_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 */
|
#endif /* RIL_DATA_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -15,122 +15,46 @@
|
|||||||
|
|
||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
#include "ril_network.h"
|
#include "ril_network.h"
|
||||||
|
#include "ril_data.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
|
#include "ril_mtu.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
|
|
||||||
#include <gutil_strv.h>
|
#include <gutil_strv.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "common.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))
|
#define CTX_ID_NONE ((unsigned int)(-1))
|
||||||
|
|
||||||
enum data_call_state {
|
#define MAX_MTU 1280
|
||||||
DATA_CALL_INACTIVE,
|
|
||||||
DATA_CALL_LINK_DOWN,
|
|
||||||
DATA_CALL_ACTIVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ril_gprs_context_state {
|
struct ril_gprs_context_call {
|
||||||
STATE_IDLE,
|
struct ril_data_call_request *req;
|
||||||
STATE_ACTIVATING,
|
ofono_gprs_context_cb_t cb;
|
||||||
STATE_DEACTIVATING,
|
gpointer data;
|
||||||
STATE_ACTIVE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_gprs_context {
|
struct ril_gprs_context {
|
||||||
struct ofono_gprs_context *gc;
|
struct ofono_gprs_context *gc;
|
||||||
struct ril_modem *modem;
|
struct ril_modem *modem;
|
||||||
struct ril_network *network;
|
struct ril_network *network;
|
||||||
GRilIoChannel *io;
|
struct ril_data *data;
|
||||||
GRilIoQueue *q;
|
|
||||||
guint active_ctx_cid;
|
guint active_ctx_cid;
|
||||||
enum ril_gprs_context_state state;
|
gulong calls_changed_event_id;
|
||||||
gulong regid;
|
struct ril_mtu_watch *mtu_watch;
|
||||||
struct ril_gprs_context_data_call *active_call;
|
struct ril_data_call *active_call;
|
||||||
struct ril_gprs_context_deactivate_req *deactivate_req;
|
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(
|
static inline struct ril_gprs_context *ril_gprs_context_get_data(
|
||||||
struct ofono_gprs_context *gprs)
|
struct ofono_gprs_context *gprs)
|
||||||
{
|
{
|
||||||
return ofono_gprs_context_get_data(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)
|
static char *ril_gprs_context_netmask(const char *address)
|
||||||
{
|
{
|
||||||
if (address) {
|
if (address) {
|
||||||
@@ -152,34 +76,6 @@ static char *ril_gprs_context_netmask(const char *address)
|
|||||||
return g_strdup("255.255.255.0");
|
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,
|
static void ril_gprs_context_set_ipv4(struct ofono_gprs_context *gc,
|
||||||
char * const *ip_addr)
|
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(
|
static void ril_gprs_context_call_done(struct ril_gprs_context_call *call,
|
||||||
struct ril_gprs_context_data_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) {
|
if (call) {
|
||||||
g_free(call->ifname);
|
ril_data_call_free(gcd->active_call);
|
||||||
g_strfreev(call->dnses);
|
gcd->active_call = ril_data_call_dup(call);
|
||||||
g_strfreev(call->addresses);
|
if (!gcd->mtu_watch) {
|
||||||
g_strfreev(call->gateways);
|
gcd->mtu_watch = ril_mtu_watch_new(MAX_MTU);
|
||||||
g_free(call);
|
}
|
||||||
|
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)
|
static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
||||||
{
|
{
|
||||||
gcd->state = STATE_IDLE;
|
|
||||||
if (gcd->active_call) {
|
if (gcd->active_call) {
|
||||||
if (gcd->deactivate_req &&
|
ril_gprs_context_free_active_call(gcd);
|
||||||
gcd->deactivate_req->cid == gcd->active_call->cid) {
|
if (gcd->deactivate.req) {
|
||||||
/* Mark this request as done */
|
ril_gprs_context_call_done(&gcd->deactivate, TRUE);
|
||||||
gcd->deactivate_req->cbd.gcd = NULL;
|
|
||||||
gcd->deactivate_req = NULL;
|
|
||||||
}
|
}
|
||||||
ril_gprs_context_data_call_free(gcd->active_call);
|
|
||||||
gcd->active_call = NULL;
|
|
||||||
}
|
}
|
||||||
if (gcd->active_ctx_cid != CTX_ID_NONE) {
|
if (gcd->active_ctx_cid != CTX_ID_NONE) {
|
||||||
guint id = gcd->active_ctx_cid;
|
guint id = gcd->active_ctx_cid;
|
||||||
gcd->active_ctx_cid = CTX_ID_NONE;
|
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||||
|
DBG("ofono context %u deactivated", id);
|
||||||
ofono_gprs_context_deactivated(gcd->gc, 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 */
|
/* Only compares the stuff that's important to us */
|
||||||
static gboolean ril_gprs_context_data_call_equal(
|
static gboolean ril_gprs_context_data_call_equal(
|
||||||
const struct ril_gprs_context_data_call *c1,
|
const struct ril_data_call *c1,
|
||||||
const struct ril_gprs_context_data_call *c2)
|
const struct ril_data_call *c2)
|
||||||
{
|
{
|
||||||
if (!c1 && !c2) {
|
if (!c1 && !c2) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -382,134 +264,58 @@ static gboolean ril_gprs_context_data_call_equal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ril_gprs_context_data_call *
|
static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
|
||||||
ril_gprs_context_parse_data_call(int version, GRilIoParser *rilp)
|
|
||||||
{
|
{
|
||||||
char *prot;
|
struct ril_gprs_context *gcd = arg;
|
||||||
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 ofono_gprs_context *gc = gcd->gc;
|
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 */
|
* gcd->active_call can't be NULL here because this callback
|
||||||
call = ril_gprs_context_data_call_find(unsol,
|
* is only registered when we have the active call and released
|
||||||
gcd->active_call->cid);
|
* when active call is dropped.
|
||||||
if (call) {
|
*/
|
||||||
/* Check if the call have been disconnected */
|
struct ril_data_call *prev_call = gcd->active_call;
|
||||||
if (call->active == DATA_CALL_INACTIVE) {
|
const struct ril_data_call *call =
|
||||||
ofono_error("Clearing active context");
|
ril_data_call_find(data->data_calls, prev_call->cid);
|
||||||
ril_gprs_context_set_disconnected(gcd);
|
|
||||||
call = NULL;
|
|
||||||
|
|
||||||
/* Compare it agains the last known state */
|
if (call) {
|
||||||
} else if (ril_gprs_context_data_call_equal(call,
|
/* Check if the call has been disconnected */
|
||||||
gcd->active_call)) {
|
if (call->active == RIL_DATA_CALL_INACTIVE) {
|
||||||
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 {
|
|
||||||
ofono_error("Clearing active context");
|
ofono_error("Clearing active context");
|
||||||
ril_gprs_context_set_disconnected(gcd);
|
ril_gprs_context_set_disconnected(gcd);
|
||||||
}
|
call = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't need the rest of the list anymore */
|
/* Compare it against the last known state */
|
||||||
ril_gprs_context_data_call_list_free(unsol);
|
} 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) {
|
if (!call) {
|
||||||
/* We are not interested */
|
/* We are not interested */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the updated call data */
|
/*
|
||||||
prev_call = gcd->active_call;
|
* prev_call points to the previous active call, and it will
|
||||||
gcd->active_call = call;
|
* 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);
|
ofono_info("data call status: %d", call->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call->active == DATA_CALL_ACTIVE) {
|
if (call->active == RIL_DATA_CALL_ACTIVE) {
|
||||||
gboolean signal = FALSE;
|
gboolean signal = FALSE;
|
||||||
|
|
||||||
if (call->ifname && g_strcmp0(call->ifname, prev_call->ifname)) {
|
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,
|
static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
||||||
const void *data, guint len, void *user_data)
|
int ril_status, const struct ril_data_call *call,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_gprs_context_cbd *cbd = user_data;
|
struct ril_gprs_context *gcd = user_data;
|
||||||
ofono_gprs_context_cb_t cb = cbd->cb;
|
|
||||||
struct ril_gprs_context *gcd = cbd->gcd;
|
|
||||||
struct ofono_gprs_context *gc = gcd->gc;
|
struct ofono_gprs_context *gc = gcd->gc;
|
||||||
struct ofono_error error;
|
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_ip_addr = NULL;
|
||||||
char **split_ipv6_addr = NULL;
|
char **split_ipv6_addr = NULL;
|
||||||
char* ip_gw = NULL;
|
char* ip_gw = NULL;
|
||||||
char* ipv6_gw = NULL;
|
char* ipv6_gw = NULL;
|
||||||
char** dns_addr = NULL;
|
char** dns_addr = NULL;
|
||||||
char** dns_ipv6_addr = NULL;
|
char** dns_ipv6_addr = NULL;
|
||||||
|
ofono_gprs_context_cb_t cb;
|
||||||
|
gpointer cb_data;
|
||||||
|
|
||||||
ofono_info("setting up data call");
|
ofono_info("setting up data call");
|
||||||
|
|
||||||
ril_error_init_ok(&error);
|
ril_error_init_failure(&error);
|
||||||
if (status != RIL_E_SUCCESS) {
|
if (ril_status != RIL_E_SUCCESS) {
|
||||||
ofono_error("GPRS context: Reply failure: %s",
|
ofono_error("GPRS context: Reply failure: %s",
|
||||||
ril_error_to_string(status));
|
ril_error_to_string(ril_status));
|
||||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
|
||||||
error.error = status;
|
|
||||||
ril_gprs_context_set_disconnected(gcd);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply = ril_gprs_context_parse_data_call_list(data, len);
|
if (call->status != PDP_FAIL_NONE) {
|
||||||
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) {
|
|
||||||
ofono_error("Unexpected data call status %d", call->status);
|
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;
|
error.error = call->status;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -657,9 +449,6 @@ static void ril_gprs_context_activate_primary_cb(GRilIoChannel *io, int status,
|
|||||||
/* Must have interface */
|
/* Must have interface */
|
||||||
if (!call->ifname) {
|
if (!call->ifname) {
|
||||||
ofono_error("GPRS context: No interface");
|
ofono_error("GPRS context: No interface");
|
||||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
|
||||||
error.error = EINVAL;
|
|
||||||
ril_gprs_context_set_disconnected(gcd);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,35 +457,25 @@ static void ril_gprs_context_activate_primary_cb(GRilIoChannel *io, int status,
|
|||||||
&split_ipv6_addr);
|
&split_ipv6_addr);
|
||||||
if (!split_ip_addr && !split_ipv6_addr) {
|
if (!split_ip_addr && !split_ipv6_addr) {
|
||||||
ofono_error("GPRS context: No IP address");
|
ofono_error("GPRS context: No IP address");
|
||||||
error.type = OFONO_ERROR_TYPE_FAILURE;
|
|
||||||
error.error = EINVAL;
|
|
||||||
ril_gprs_context_set_disconnected(gcd);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Steal the call data from the list */
|
ril_error_init_ok(&error);
|
||||||
g_slist_free(reply->calls);
|
ril_gprs_context_set_active_call(gcd, call);
|
||||||
reply->calls = NULL;
|
|
||||||
ril_gprs_context_data_call_free(gcd->active_call);
|
GASSERT(!gcd->calls_changed_event_id);
|
||||||
gcd->active_call = call;
|
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||||
gcd->state = STATE_ACTIVE;
|
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);
|
ofono_gprs_context_set_interface(gc, call->ifname);
|
||||||
ril_gprs_split_gw_by_protocol(call->gateways, &ip_gw, &ipv6_gw);
|
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);
|
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 &&
|
if (split_ipv6_addr &&
|
||||||
(call->prot == OFONO_GPRS_PROTO_IPV6 ||
|
(call->prot == OFONO_GPRS_PROTO_IPV6 ||
|
||||||
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
|
call->prot == OFONO_GPRS_PROTO_IPV4V6)) {
|
||||||
|
|
||||||
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
|
ril_gprs_context_set_ipv6(gc, split_ipv6_addr);
|
||||||
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
ofono_gprs_context_set_ipv6_gateway(gc, ipv6_gw);
|
||||||
ofono_gprs_context_set_ipv6_dns_servers(gc,
|
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:
|
done:
|
||||||
ril_gprs_context_data_call_list_free(reply);
|
|
||||||
g_strfreev(split_ip_addr);
|
g_strfreev(split_ip_addr);
|
||||||
g_strfreev(split_ipv6_addr);
|
g_strfreev(split_ipv6_addr);
|
||||||
g_strfreev(dns_addr);
|
g_strfreev(dns_addr);
|
||||||
@@ -721,7 +499,17 @@ done:
|
|||||||
g_free(ip_gw);
|
g_free(ip_gw);
|
||||||
g_free(ipv6_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,
|
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 ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
||||||
struct ofono_netreg *netreg = ril_modem_ofono_netreg(gcd->modem);
|
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 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 */
|
/* Let's make sure that we aren't connecting when roaming not allowed */
|
||||||
if (rs == NETWORK_REGISTRATION_STATUS_ROAMING) {
|
if (rs == NETWORK_REGISTRATION_STATUS_ROAMING) {
|
||||||
|
struct ofono_gprs *gprs = ril_modem_ofono_gprs(gcd->modem);
|
||||||
if (!ofono_gprs_get_roaming_allowed(gprs) &&
|
if (!ofono_gprs_get_roaming_allowed(gprs) &&
|
||||||
ril_netreg_check_if_really_roaming(netreg, rs) ==
|
ril_netreg_check_if_really_roaming(netreg, rs) ==
|
||||||
NETWORK_REGISTRATION_STATUS_ROAMING) {
|
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);
|
ofono_info("Activating context: %d", ctx->cid);
|
||||||
protocol_str = ril_gprs_ofono_protocol_to_ril(ctx->proto);
|
GASSERT(!gcd->activate.req);
|
||||||
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(ctx->cid != CTX_ID_NONE);
|
GASSERT(ctx->cid != CTX_ID_NONE);
|
||||||
|
|
||||||
gcd->active_ctx_cid = ctx->cid;
|
gcd->active_ctx_cid = ctx->cid;
|
||||||
gcd->state = STATE_ACTIVATING;
|
gcd->activate.cb = cb;
|
||||||
|
gcd->activate.data = data;
|
||||||
grilio_queue_send_request_full(gcd->q, req, RIL_REQUEST_SETUP_DATA_CALL,
|
gcd->activate.req = ril_data_call_setup(gcd->data, ctx,
|
||||||
ril_gprs_context_activate_primary_cb, ril_gprs_context_cbd_free,
|
ril_gprs_context_activate_primary_cb, gcd);
|
||||||
ril_gprs_context_cbd_new(gcd, cb, data));
|
|
||||||
grilio_request_unref(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_gprs_context_deactivate_data_call_cb(GRilIoChannel *io, int err,
|
static void ril_gprs_context_deactivate_primary_cb(struct ril_data *data,
|
||||||
const void *data, guint len, void *user_data)
|
int ril_status, void *user_data)
|
||||||
{
|
{
|
||||||
|
struct ril_gprs_context *gcd = user_data;
|
||||||
struct ofono_error error;
|
struct ofono_error error;
|
||||||
struct ril_gprs_context_deactivate_req *req = user_data;
|
ofono_gprs_context_cb_t cb;
|
||||||
struct ril_gprs_context *gcd = req->cbd.gcd;
|
gpointer cb_data;
|
||||||
|
|
||||||
if (!gcd) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
/*
|
GASSERT(gcd->active_call);
|
||||||
* ril_gprs_context_remove() zeroes gcd pointer for the
|
ril_error_init_ok(&error);
|
||||||
* pending ril_gprs_context_deactivate_req. Or we may have
|
ofono_info("Deactivated data call");
|
||||||
* 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);
|
|
||||||
} else {
|
} else {
|
||||||
ofono_gprs_context_cb_t cb = req->cbd.cb;
|
ril_error_init_failure(&error);
|
||||||
|
ofono_error("Deactivate failure: %s",
|
||||||
/* Mark it as done */
|
ril_error_to_string(ril_status));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_gprs_context_deactivate_data_call(struct ril_gprs_context *gcd,
|
cb = gcd->deactivate.cb;
|
||||||
ofono_gprs_context_cb_t cb, void *data)
|
cb_data = gcd->deactivate.data;
|
||||||
{
|
GASSERT(gcd->deactivate.req);
|
||||||
GRilIoRequest *req = grilio_request_new();
|
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
|
||||||
|
|
||||||
/* Overlapping deactivate requests make no sense */
|
if (cb) {
|
||||||
GASSERT(!gcd->deactivate_req);
|
ril_gprs_context_free_active_call(gcd);
|
||||||
if (gcd->deactivate_req) {
|
cb(&error, cb_data);
|
||||||
gcd->deactivate_req->cbd.gcd = NULL;
|
} 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,
|
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);
|
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
||||||
|
|
||||||
GASSERT(cb);
|
|
||||||
GASSERT(gcd->active_call && gcd->active_ctx_cid == id);
|
GASSERT(gcd->active_call && gcd->active_ctx_cid == id);
|
||||||
ofono_info("Deactivate primary");
|
ofono_info("Deactivate primary");
|
||||||
|
|
||||||
if (gcd->active_call && gcd->active_ctx_cid == id) {
|
if (gcd->active_call && gcd->active_ctx_cid == id) {
|
||||||
ril_gprs_context_deactivate_data_call(gcd, cb, data);
|
gcd->deactivate.cb = cb;
|
||||||
} else {
|
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;
|
struct ofono_error error;
|
||||||
cb(ril_error_ok(&error), data);
|
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,
|
static void ril_gprs_context_detach_shutdown(struct ofono_gprs_context *gc,
|
||||||
unsigned int id)
|
unsigned int id)
|
||||||
{
|
{
|
||||||
struct ril_gprs_context *gcd = ril_gprs_context_get_data(gc);
|
|
||||||
|
|
||||||
DBG("%d", id);
|
DBG("%d", id);
|
||||||
GASSERT(gcd->active_ctx_cid == id);
|
ril_gprs_context_deactivate_primary(gc, id, NULL, NULL);
|
||||||
if (gcd->active_call && !gcd->deactivate_req) {
|
|
||||||
ril_gprs_context_deactivate_data_call(gcd, NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ril_gprs_context_probe(struct ofono_gprs_context *gc,
|
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->gc = gc;
|
||||||
gcd->modem = modem;
|
gcd->modem = modem;
|
||||||
gcd->network = ril_network_ref(modem->network);
|
gcd->network = ril_network_ref(modem->network);
|
||||||
gcd->io = grilio_channel_ref(ril_modem_io(modem));
|
gcd->data = ril_data_ref(modem->data);
|
||||||
gcd->q = grilio_queue_new(gcd->io);
|
gcd->active_ctx_cid = CTX_ID_NONE;
|
||||||
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);
|
|
||||||
ofono_gprs_context_set_data(gc, gcd);
|
ofono_gprs_context_set_data(gc, gcd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -937,20 +627,21 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
|||||||
DBG("");
|
DBG("");
|
||||||
ofono_gprs_context_set_data(gc, NULL);
|
ofono_gprs_context_set_data(gc, NULL);
|
||||||
|
|
||||||
if (gcd->active_call && !gcd->deactivate_req) {
|
ril_data_call_request_cancel(gcd->activate.req);
|
||||||
ril_gprs_context_deactivate_data_call(gcd, NULL, NULL);
|
|
||||||
}
|
if (gcd->deactivate.req) {
|
||||||
|
/* Let it complete but we won't be around to be notified. */
|
||||||
if (gcd->deactivate_req) {
|
ril_data_call_request_detach(gcd->deactivate.req);
|
||||||
gcd->deactivate_req->cbd.gcd = NULL;
|
} 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);
|
ril_network_unref(gcd->network);
|
||||||
grilio_channel_remove_handler(gcd->io, gcd->regid);
|
ril_data_call_free(gcd->active_call);
|
||||||
grilio_channel_unref(gcd->io);
|
ril_mtu_watch_free(gcd->mtu_watch);
|
||||||
grilio_queue_cancel_all(gcd->q, FALSE);
|
|
||||||
grilio_queue_unref(gcd->q);
|
|
||||||
ril_gprs_context_data_call_free(gcd->active_call);
|
|
||||||
g_free(gcd);
|
g_free(gcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ struct ril_modem_data {
|
|||||||
ril_modem_cb_t removed_cb;
|
ril_modem_cb_t removed_cb;
|
||||||
void *removed_cb_data;
|
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_online;
|
||||||
struct ril_modem_online_request set_offline;
|
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;
|
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)
|
static void ril_modem_check_devinfo(struct ril_modem_data *md)
|
||||||
{
|
{
|
||||||
/* devinfo driver assumes that IMEI is known */
|
/* devinfo driver assumes that IMEI is known */
|
||||||
@@ -208,7 +220,8 @@ static gboolean ril_modem_online_request_timeout(gpointer data)
|
|||||||
req->data = NULL;
|
req->data = NULL;
|
||||||
cb(ril_error_failure(&error), cb_data);
|
cb(ril_error_failure(&error), cb_data);
|
||||||
ril_modem_update_online_state(req->md);
|
ril_modem_update_online_state(req->md);
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_modem_online_check(gpointer data)
|
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);
|
GASSERT(md->modem.radio == radio);
|
||||||
ril_modem_update_radio_settings(md);
|
ril_modem_update_radio_settings(md);
|
||||||
ril_modem_update_online_state(md);
|
ril_modem_update_online_state(md);
|
||||||
};
|
}
|
||||||
|
|
||||||
static void ril_modem_pre_sim(struct ofono_modem *modem)
|
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),
|
DBG("%s going %sline", ofono_modem_get_path(modem),
|
||||||
online ? "on" : "off");
|
online ? "on" : "off");
|
||||||
|
|
||||||
|
if (md->online_cb) {
|
||||||
|
md->online_cb(&md->modem, online, md->online_cb_data);
|
||||||
|
}
|
||||||
|
|
||||||
if (online) {
|
if (online) {
|
||||||
ril_radio_power_on(md->modem.radio, RADIO_POWER_TAG(md));
|
ril_radio_power_on(md->modem.radio, RADIO_POWER_TAG(md));
|
||||||
req = &md->set_online;
|
req = &md->set_online;
|
||||||
@@ -449,7 +466,6 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
|||||||
err = ofono_modem_register(ofono);
|
err = ofono_modem_register(ofono);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
ril_radio_power_cycle(modem->radio);
|
ril_radio_power_cycle(modem->radio);
|
||||||
ril_radio_power_on(modem->radio, RADIO_POWER_TAG(md));
|
|
||||||
GASSERT(io->connected);
|
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);
|
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) {
|
if (nd->current_operator_id) {
|
||||||
g_source_remove(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);
|
ril_network_cb_t cb, void *arg);
|
||||||
void ril_network_remove_handler(struct ril_network *net, gulong id);
|
void ril_network_remove_handler(struct ril_network *net, gulong id);
|
||||||
|
|
||||||
#endif /* RIL_NETWORK */
|
#endif /* RIL_NETWORK_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
#include "ril_sim_card.h"
|
#include "ril_sim_card.h"
|
||||||
|
#include "ril_sim_info.h"
|
||||||
#include "ril_network.h"
|
#include "ril_network.h"
|
||||||
#include "ril_radio.h"
|
#include "ril_radio.h"
|
||||||
#include "ril_data.h"
|
#include "ril_data.h"
|
||||||
@@ -78,10 +79,12 @@ struct ril_plugin_priv {
|
|||||||
struct ril_data_manager *data_manager;
|
struct ril_data_manager *data_manager;
|
||||||
GSList *slots;
|
GSList *slots;
|
||||||
ril_slot_info_ptr *slots_info;
|
ril_slot_info_ptr *slots_info;
|
||||||
struct ril_slot *data_slot;
|
|
||||||
struct ril_slot *voice_slot;
|
struct ril_slot *voice_slot;
|
||||||
|
struct ril_slot *data_slot;
|
||||||
|
struct ril_slot *mms_slot;
|
||||||
char *default_voice_imsi;
|
char *default_voice_imsi;
|
||||||
char *default_data_imsi;
|
char *default_data_imsi;
|
||||||
|
char *mms_imsi;
|
||||||
GKeyFile *storage;
|
GKeyFile *storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,15 +98,17 @@ struct ril_slot {
|
|||||||
gint timeout; /* RIL timeout, in milliseconds */
|
gint timeout; /* RIL timeout, in milliseconds */
|
||||||
int index;
|
int index;
|
||||||
int sim_flags;
|
int sim_flags;
|
||||||
|
gboolean online;
|
||||||
struct ril_slot_config config;
|
struct ril_slot_config config;
|
||||||
struct ril_plugin_priv *plugin;
|
struct ril_plugin_priv *plugin;
|
||||||
struct ril_sim_dbus *sim_dbus;
|
|
||||||
struct ril_modem *modem;
|
struct ril_modem *modem;
|
||||||
struct ril_mce *mce;
|
struct ril_mce *mce;
|
||||||
struct ofono_sim *sim;
|
struct ofono_sim *sim;
|
||||||
struct ril_radio *radio;
|
struct ril_radio *radio;
|
||||||
struct ril_network *network;
|
struct ril_network *network;
|
||||||
struct ril_sim_card *sim_card;
|
struct ril_sim_card *sim_card;
|
||||||
|
struct ril_sim_info *sim_info;
|
||||||
|
struct ril_sim_info_dbus *sim_info_dbus;
|
||||||
struct ril_data *data;
|
struct ril_data *data;
|
||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
gulong io_event_id[IO_EVENT_COUNT];
|
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_dump_notify(struct ofono_debug_desc *desc);
|
||||||
static void ril_debug_grilio_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_retry_init_io(struct ril_slot *slot);
|
||||||
static void ril_plugin_update_modem_paths_full(struct ril_plugin_priv *plugin);
|
|
||||||
|
|
||||||
GLOG_MODULE_DEFINE("rilmodem");
|
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,
|
ofono_sim_remove_state_watch(slot->sim,
|
||||||
slot->sim_state_watch_id);
|
slot->sim_state_watch_id);
|
||||||
}
|
}
|
||||||
|
ril_sim_info_set_ofono_sim(slot->sim_info, NULL);
|
||||||
slot->sim = NULL;
|
slot->sim = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,6 +326,9 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
|
|||||||
{
|
{
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
struct ril_slot *slot = NULL;
|
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 */
|
/* Voice */
|
||||||
if (plugin->default_voice_imsi) {
|
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);
|
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) {
|
if (plugin->data_slot != slot) {
|
||||||
mask |= RIL_PLUGIN_SIGNAL_DATA_PATH;
|
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;
|
plugin->data_slot = slot;
|
||||||
if (slot) {
|
if (slot) {
|
||||||
DBG("Default data SIM at %s", slot->path);
|
DBG("Default data SIM at %s", slot->path);
|
||||||
plugin->pub.default_data_path = slot->path;
|
plugin->pub.default_data_path = slot->path;
|
||||||
ril_data_allow(slot->data, TRUE);
|
|
||||||
} else {
|
} else {
|
||||||
DBG("No default data SIM");
|
DBG("No default data SIM");
|
||||||
plugin->pub.default_data_path = NULL;
|
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;
|
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));
|
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)
|
static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
||||||
{
|
{
|
||||||
struct ril_slot *slot = 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)
|
void *data)
|
||||||
{
|
{
|
||||||
struct ril_slot *slot = data;
|
struct ril_slot *slot = data;
|
||||||
|
struct ril_plugin_priv *plugin = slot->plugin;
|
||||||
|
|
||||||
DBG("%s sim state %d", slot->path + 1, new_state);
|
DBG("%s sim state %d", slot->path + 1, new_state);
|
||||||
slot->sim_state = new_state;
|
slot->sim_state = new_state;
|
||||||
ril_plugin_check_sim_state(slot);
|
if (new_state == OFONO_SIM_STATE_READY) {
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
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)
|
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);
|
||||||
GASSERT(slot->sim_watch_id);
|
GASSERT(slot->sim_watch_id);
|
||||||
GASSERT(!slot->sim_state_watch_id);
|
GASSERT(!slot->sim_state_watch_id);
|
||||||
|
|
||||||
slot->sim = sim;
|
slot->sim = sim;
|
||||||
slot->sim_state = ofono_sim_get_state(sim);
|
slot->sim_state = ofono_sim_get_state(sim);
|
||||||
slot->sim_state_watch_id = ofono_sim_add_state_watch(sim,
|
slot->sim_state_watch_id = ofono_sim_add_state_watch(sim,
|
||||||
ril_plugin_sim_state_watch, slot,
|
ril_plugin_sim_state_watch, slot,
|
||||||
ril_plugin_sim_state_watch_done);
|
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,
|
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));
|
ril_plugin_register_sim(slot, __ofono_atom_get_data(atom));
|
||||||
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
|
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
|
||||||
DBG("%s sim unregistered", slot->path + 1);
|
DBG("%s sim unregistered", slot->path + 1);
|
||||||
|
ril_sim_info_set_ofono_sim(slot->sim_info, NULL);
|
||||||
slot->sim = NULL;
|
slot->sim = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ril_plugin_check_sim_state(slot);
|
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
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);
|
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)
|
static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
|
||||||
{
|
{
|
||||||
struct ril_slot *slot = 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);
|
||||||
GASSERT(slot->modem == modem);
|
GASSERT(slot->modem == modem);
|
||||||
|
|
||||||
if (slot->sim_dbus) {
|
if (slot->sim_info_dbus) {
|
||||||
ril_sim_dbus_free(slot->sim_dbus);
|
ril_sim_info_dbus_free(slot->sim_info_dbus);
|
||||||
slot->sim_dbus = NULL;
|
slot->sim_info_dbus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->modem = NULL;
|
slot->modem = NULL;
|
||||||
|
slot->online = FALSE;
|
||||||
ril_data_allow(slot->data, FALSE);
|
ril_data_allow(slot->data, FALSE);
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
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,
|
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);
|
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_removed_cb(modem, ril_plugin_modem_removed, slot);
|
||||||
|
ril_modem_set_online_cb(modem, ril_plugin_modem_online, slot);
|
||||||
} else {
|
} else {
|
||||||
ril_plugin_shutdown_slot(slot, TRUE);
|
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);
|
slot->sim_card, ril_plugin_sim_state_changed, slot);
|
||||||
|
|
||||||
GASSERT(!slot->data);
|
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)) {
|
if (ril_plugin_multisim(slot->plugin)) {
|
||||||
ril_data_set_name(slot->data, slot->path + 1);
|
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);
|
GASSERT(slot->retry_id);
|
||||||
slot->retry_id = 0;
|
slot->retry_id = 0;
|
||||||
ril_plugin_init_io(slot);
|
ril_plugin_init_io(slot);
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_retry_init_io(struct ril_slot *slot)
|
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)
|
static void ril_plugin_delete_slot(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
ril_plugin_shutdown_slot(slot, TRUE);
|
ril_plugin_shutdown_slot(slot, TRUE);
|
||||||
|
ril_sim_info_unref(slot->sim_info);
|
||||||
g_free(slot->path);
|
g_free(slot->path);
|
||||||
g_free(slot->imei);
|
g_free(slot->imei);
|
||||||
g_free(slot->name);
|
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)
|
static void ril_plugin_init_slots(struct ril_plugin_priv *plugin)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -1237,6 +1355,7 @@ static void ril_plugin_init_slots(struct ril_plugin_priv *plugin)
|
|||||||
slot->plugin = plugin;
|
slot->plugin = plugin;
|
||||||
slot->pub.path = slot->path;
|
slot->pub.path = slot->path;
|
||||||
slot->pub.config = &slot->config;
|
slot->pub.config = &slot->config;
|
||||||
|
slot->sim_info = ril_sim_info_new(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
*info = NULL;
|
*info = NULL;
|
||||||
@@ -1397,6 +1516,7 @@ static void ril_plugin_exit(void)
|
|||||||
g_free(ril_plugin->slots_info);
|
g_free(ril_plugin->slots_info);
|
||||||
g_free(ril_plugin->default_voice_imsi);
|
g_free(ril_plugin->default_voice_imsi);
|
||||||
g_free(ril_plugin->default_data_imsi);
|
g_free(ril_plugin->default_data_imsi);
|
||||||
|
g_free(ril_plugin->mms_imsi);
|
||||||
g_free(ril_plugin);
|
g_free(ril_plugin);
|
||||||
ril_plugin = NULL;
|
ril_plugin = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ struct ril_slot_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ril_plugin {
|
struct ril_plugin {
|
||||||
|
const char *mms_imsi;
|
||||||
|
const char *mms_path;
|
||||||
const char *default_voice_imsi;
|
const char *default_voice_imsi;
|
||||||
const char *default_data_imsi;
|
const char *default_data_imsi;
|
||||||
const char *default_voice_path;
|
const char *default_voice_path;
|
||||||
@@ -81,12 +83,17 @@ struct ril_modem {
|
|||||||
#define RIL_PLUGIN_SIGNAL_VOICE_IMSI (0x01)
|
#define RIL_PLUGIN_SIGNAL_VOICE_IMSI (0x01)
|
||||||
#define RIL_PLUGIN_SIGNAL_DATA_IMSI (0x02)
|
#define RIL_PLUGIN_SIGNAL_DATA_IMSI (0x02)
|
||||||
#define RIL_PLUGIN_SIGNAL_VOICE_PATH (0x04)
|
#define RIL_PLUGIN_SIGNAL_VOICE_PATH (0x04)
|
||||||
#define RIL_PLUGIN_SIGNAL_DATA_PATH (0x10)
|
#define RIL_PLUGIN_SIGNAL_DATA_PATH (0x08)
|
||||||
#define RIL_PLUGIN_SIGNAL_ENABLED_SLOTS (0x20)
|
#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_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);
|
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,
|
void ril_plugin_set_default_voice_imsi(struct ril_plugin *plugin,
|
||||||
const char *imsi);
|
const char *imsi);
|
||||||
void ril_plugin_set_default_data_imsi(struct ril_plugin *plugin,
|
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);
|
const char *ril_sim_dbus_imsi(struct ril_sim_dbus *dbus);
|
||||||
void ril_sim_dbus_free(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);
|
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_free(struct ril_plugin_dbus *dbus);
|
||||||
void ril_plugin_dbus_block_imei_requests(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);
|
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 ril_modem_set_removed_cb(struct ril_modem *modem, ril_modem_cb_t cb,
|
||||||
void *data);
|
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_get_path(modem) ofono_modem_get_path((modem)->ofono)
|
||||||
#define ril_modem_4g_enabled(modem) ((modem)->config.enable_4g)
|
#define ril_modem_4g_enabled(modem) ((modem)->config.enable_4g)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -41,18 +41,21 @@ struct ril_plugin_dbus {
|
|||||||
DBusConnection *conn;
|
DBusConnection *conn;
|
||||||
gboolean block_imei_req;
|
gboolean block_imei_req;
|
||||||
GSList *blocked_imei_req;
|
GSList *blocked_imei_req;
|
||||||
|
guint mms_watch;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RIL_DBUS_PATH "/"
|
#define RIL_DBUS_PATH "/"
|
||||||
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
|
#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_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
|
||||||
#define RIL_DBUS_PRESENT_SIMS_CHANGED_SIGNAL "PresentSimsChanged"
|
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
|
||||||
#define RIL_DBUS_DEFAULT_VOICE_SIM_CHANGED_SIGNAL "DefaultVoiceSimChanged"
|
#define RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED "DefaultVoiceSimChanged"
|
||||||
#define RIL_DBUS_DEFAULT_DATA_SIM_CHANGED_SIGNAL "DefaultDataSimChanged"
|
#define RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED "DefaultDataSimChanged"
|
||||||
#define RIL_DBUS_DEFAULT_VOICE_MODEM_CHANGED_SIGNAL "DefaultVoiceModemChanged"
|
#define RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED "DefaultVoiceModemChanged"
|
||||||
#define RIL_DBUS_DEFAULT_DATA_MODEM_CHANGED_SIGNAL "DefaultDataModemChanged"
|
#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"
|
#define RIL_DBUS_IMSI_AUTO "auto"
|
||||||
|
|
||||||
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
|
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);
|
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)
|
static void ril_plugin_dbus_append_imsi(DBusMessageIter *it, const char *imsi)
|
||||||
{
|
{
|
||||||
if (!imsi) imsi = RIL_DBUS_IMSI_AUTO;
|
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);
|
name, DBUS_TYPE_STRING, &imsi, DBUS_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ril_plugin_dbus_signal_path(struct ril_plugin_dbus *dbus,
|
static inline void ril_plugin_dbus_signal_string(struct ril_plugin_dbus *dbus,
|
||||||
const char *name, const char *path)
|
const char *name, const char *str)
|
||||||
{
|
{
|
||||||
if (!path) path = "";
|
if (!str) str = "";
|
||||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
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)
|
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 (dbus) {
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_VOICE_IMSI) {
|
if (mask & RIL_PLUGIN_SIGNAL_VOICE_IMSI) {
|
||||||
ril_plugin_dbus_signal_imsi(dbus,
|
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);
|
dbus->plugin->default_voice_imsi);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_DATA_IMSI) {
|
if (mask & RIL_PLUGIN_SIGNAL_DATA_IMSI) {
|
||||||
ril_plugin_dbus_signal_imsi(dbus,
|
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);
|
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) {
|
if (mask & RIL_PLUGIN_SIGNAL_ENABLED_SLOTS) {
|
||||||
ril_plugin_dbus_signal_path_array(dbus,
|
ril_plugin_dbus_signal_path_array(dbus,
|
||||||
RIL_DBUS_ENABLED_MODEMS_CHANGED_SIGNAL,
|
RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
|
||||||
ril_plugin_dbus_enabled);
|
ril_plugin_dbus_enabled);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_VOICE_PATH) {
|
if (mask & RIL_PLUGIN_SIGNAL_VOICE_PATH) {
|
||||||
ril_plugin_dbus_signal_path(dbus,
|
ril_plugin_dbus_signal_string(dbus,
|
||||||
RIL_DBUS_DEFAULT_VOICE_MODEM_CHANGED_SIGNAL,
|
RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
|
||||||
dbus->plugin->default_voice_path);
|
dbus->plugin->default_voice_path);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_DATA_PATH) {
|
if (mask & RIL_PLUGIN_SIGNAL_DATA_PATH) {
|
||||||
ril_plugin_dbus_signal_path(dbus,
|
ril_plugin_dbus_signal_string(dbus,
|
||||||
RIL_DBUS_DEFAULT_DATA_MODEM_CHANGED_SIGNAL,
|
RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
|
||||||
dbus->plugin->default_data_path);
|
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;
|
dbus_bool_t value = present;
|
||||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
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_INT32, &index,
|
||||||
DBUS_TYPE_BOOLEAN, &value,
|
DBUS_TYPE_BOOLEAN, &value,
|
||||||
DBUS_TYPE_INVALID);
|
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);
|
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,
|
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -344,6 +371,13 @@ static DBusMessage *ril_plugin_dbus_get_all3(DBusConnection *conn,
|
|||||||
ril_plugin_dbus_append_all3);
|
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,
|
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -391,6 +425,17 @@ static DBusMessage *ril_plugin_dbus_get_imei(DBusConnection *conn,
|
|||||||
ril_plugin_dbus_append_imei_array);
|
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,
|
static DBusMessage *ril_plugin_dbus_reply_with_imsi(DBusMessage *msg,
|
||||||
const char *imsi)
|
const char *imsi)
|
||||||
{
|
{
|
||||||
@@ -420,6 +465,14 @@ static DBusMessage *ril_plugin_dbus_get_default_voice_sim(DBusConnection *conn,
|
|||||||
dbus->plugin->default_voice_imsi);
|
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,
|
static DBusMessage *ril_plugin_dbus_reply_with_path(DBusMessage *msg,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
@@ -449,6 +502,14 @@ static DBusMessage *ril_plugin_dbus_get_default_voice_modem(DBusConnection *conn
|
|||||||
dbus->plugin->default_voice_path);
|
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,
|
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
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);
|
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[] = {
|
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||||
{ GDBUS_METHOD("GetAll", NULL,
|
{ GDBUS_METHOD("GetAll",
|
||||||
GDBUS_ARGS({"version", "i" },
|
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
|
||||||
{"availableModems", "ao" },
|
|
||||||
{"enabledModems", "ao" },
|
|
||||||
{"defaultDataSim", "s" },
|
|
||||||
{"defaultVoiceSim", "s" },
|
|
||||||
{"defaultDataModem", "s" },
|
|
||||||
{"defaultVoiceModem" , "s"}),
|
|
||||||
ril_plugin_dbus_get_all) },
|
ril_plugin_dbus_get_all) },
|
||||||
{ GDBUS_METHOD("GetAll2", NULL,
|
{ GDBUS_METHOD("GetAll2",
|
||||||
GDBUS_ARGS({"version", "i" },
|
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL2_ARGS),
|
||||||
{"availableModems", "ao" },
|
|
||||||
{"enabledModems", "ao" },
|
|
||||||
{"defaultDataSim", "s" },
|
|
||||||
{"defaultVoiceSim", "s" },
|
|
||||||
{"defaultDataModem", "s" },
|
|
||||||
{"defaultVoiceModem" , "s"},
|
|
||||||
{"presentSims" , "ab"}),
|
|
||||||
ril_plugin_dbus_get_all2) },
|
ril_plugin_dbus_get_all2) },
|
||||||
{ GDBUS_ASYNC_METHOD("GetAll3", NULL,
|
{ GDBUS_ASYNC_METHOD("GetAll3",
|
||||||
GDBUS_ARGS({"version", "i" },
|
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL3_ARGS),
|
||||||
{"availableModems", "ao" },
|
|
||||||
{"enabledModems", "ao" },
|
|
||||||
{"defaultDataSim", "s" },
|
|
||||||
{"defaultVoiceSim", "s" },
|
|
||||||
{"defaultDataModem", "s" },
|
|
||||||
{"defaultVoiceModem" , "s"},
|
|
||||||
{"presentSims" , "ab"},
|
|
||||||
{"imei" , "as"}),
|
|
||||||
ril_plugin_dbus_get_all3) },
|
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",
|
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||||
ril_plugin_dbus_get_interface_version) },
|
ril_plugin_dbus_get_interface_version) },
|
||||||
@@ -571,12 +706,18 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
|||||||
{ GDBUS_METHOD("GetDefaultVoiceSim",
|
{ GDBUS_METHOD("GetDefaultVoiceSim",
|
||||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||||
ril_plugin_dbus_get_default_voice_sim) },
|
ril_plugin_dbus_get_default_voice_sim) },
|
||||||
|
{ GDBUS_METHOD("GetMmsSim",
|
||||||
|
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||||
|
ril_plugin_dbus_get_mms_sim) },
|
||||||
{ GDBUS_METHOD("GetDefaultDataModem",
|
{ GDBUS_METHOD("GetDefaultDataModem",
|
||||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||||
ril_plugin_dbus_get_default_data_modem) },
|
ril_plugin_dbus_get_default_data_modem) },
|
||||||
{ GDBUS_METHOD("GetDefaultVoiceModem",
|
{ GDBUS_METHOD("GetDefaultVoiceModem",
|
||||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||||
ril_plugin_dbus_get_default_voice_modem) },
|
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_METHOD("SetEnabledModems",
|
||||||
GDBUS_ARGS({ "modems", "ao" }), NULL,
|
GDBUS_ARGS({ "modems", "ao" }), NULL,
|
||||||
ril_plugin_dbus_set_enabled_modems) },
|
ril_plugin_dbus_set_enabled_modems) },
|
||||||
@@ -586,22 +727,29 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
|||||||
{ GDBUS_METHOD("SetDefaultVoiceSim",
|
{ GDBUS_METHOD("SetDefaultVoiceSim",
|
||||||
GDBUS_ARGS({ "imsi", "s" }), NULL,
|
GDBUS_ARGS({ "imsi", "s" }), NULL,
|
||||||
ril_plugin_dbus_set_default_voice_sim) },
|
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[] = {
|
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_ARGS({ "modems", "ao" })) },
|
||||||
{ GDBUS_SIGNAL(RIL_DBUS_PRESENT_SIMS_CHANGED_SIGNAL,
|
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
|
||||||
GDBUS_ARGS({"index", "i" },
|
GDBUS_ARGS({"index", "i" },
|
||||||
{"present" , "b"})) },
|
{"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_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_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_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" })) },
|
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)
|
void ril_plugin_dbus_free(struct ril_plugin_dbus *dbus)
|
||||||
{
|
{
|
||||||
if (dbus) {
|
if (dbus) {
|
||||||
|
if (dbus->mms_watch) {
|
||||||
|
g_dbus_remove_watch(dbus->conn, dbus->mms_watch);
|
||||||
|
}
|
||||||
|
|
||||||
g_slist_free_full(dbus->blocked_imei_req,
|
g_slist_free_full(dbus->blocked_imei_req,
|
||||||
ril_plugin_dbus_cancel_request);
|
ril_plugin_dbus_cancel_request);
|
||||||
g_dbus_unregister_interface(dbus->conn, RIL_DBUS_PATH,
|
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);
|
GASSERT(priv->retry_id);
|
||||||
priv->retry_id = 0;
|
priv->retry_id = 0;
|
||||||
ril_radio_submit_power_request(self, ril_radio_power_should_be_on(self));
|
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)
|
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)) {
|
if (G_LIKELY(self)) {
|
||||||
struct ril_radio_priv *priv = self->priv;
|
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);
|
if (!g_hash_table_contains(priv->req_table, tag)) {
|
||||||
g_hash_table_insert(priv->req_table, tag, tag);
|
gboolean was_on = ril_radio_power_should_be_on(self);
|
||||||
if (!was_on) {
|
|
||||||
ril_radio_power_request(self, TRUE, FALSE);
|
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)) {
|
if (G_LIKELY(self)) {
|
||||||
struct ril_radio_priv *priv = self->priv;
|
struct ril_radio_priv *priv = self->priv;
|
||||||
|
|
||||||
DBG("%s%p", priv->log_prefix, tag);
|
if (g_hash_table_remove(priv->req_table, tag)) {
|
||||||
if (g_hash_table_remove(priv->req_table, tag) &&
|
DBG("%s%p", priv->log_prefix, tag);
|
||||||
!ril_radio_power_should_be_on(self)) {
|
if (!ril_radio_power_should_be_on(self)) {
|
||||||
/* The last one turns the lights off */
|
/* The last one turns the lights off */
|
||||||
ril_radio_power_request(self, FALSE, FALSE);
|
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);
|
void ril_radio_remove_handler(struct ril_radio *radio, gulong id);
|
||||||
enum ril_radio_state ril_radio_state_parse(const void *data, guint len);
|
enum ril_radio_state ril_radio_state_parse(const void *data, guint len);
|
||||||
|
|
||||||
#endif /* RIL_RADIO */
|
#endif /* RIL_RADIO_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* 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,
|
static struct ril_sim_pin_cbd *ril_sim_pin_cbd_new(struct ril_sim *sd,
|
||||||
enum ofono_sim_password_type passwd_type,
|
enum ofono_sim_password_type passwd_type,
|
||||||
|
gboolean state_change_expected,
|
||||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim_pin_cbd *cbd = g_new0(struct ril_sim_pin_cbd, 1);
|
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->data = data;
|
||||||
cbd->passwd_type = passwd_type;
|
cbd->passwd_type = passwd_type;
|
||||||
cbd->card = ril_sim_card_ref(sd->card);
|
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);
|
ril_sim_pin_cbd_state_event_count_cb, cbd);
|
||||||
|
}
|
||||||
return 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);
|
GASSERT(sd->query_passwd_state_cb);
|
||||||
sd->query_passwd_state_timeout_id = 0;
|
sd->query_passwd_state_timeout_id = 0;
|
||||||
ril_sim_finish_passwd_state_query(sd, OFONO_SIM_PASSWORD_INVALID);
|
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,
|
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);
|
sd->pin_cbd_list = g_list_remove(sd->pin_cbd_list, cbd);
|
||||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||||
ril_sim_pin_cbd_free(cbd);
|
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,
|
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);
|
ril_status, cbd->passwd_type, retry_count);
|
||||||
|
|
||||||
cbd->ril_status = ril_status;
|
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(!g_list_find(sd->pin_cbd_list, cbd));
|
||||||
GASSERT(!cbd->timeout_id);
|
GASSERT(!cbd->timeout_id);
|
||||||
@@ -862,7 +869,7 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
|||||||
} else {
|
} else {
|
||||||
struct ofono_error error;
|
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) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
cbd->cb(ril_error_ok(&error), cbd->data);
|
cbd->cb(ril_error_ok(&error), cbd->data);
|
||||||
} else {
|
} 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));
|
DBG("%s,aid=%s", passwd, ril_sim_app_id(sd));
|
||||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PIN,
|
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_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);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,7 +925,7 @@ static guint ril_perso_change_state(struct ofono_sim *sim,
|
|||||||
if (req) {
|
if (req) {
|
||||||
id = grilio_queue_send_request_full(sd->q, req, code,
|
id = grilio_queue_send_request_full(sd->q, req, code,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
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);
|
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,
|
id = grilio_queue_send_request_full(sd->q, req,
|
||||||
RIL_REQUEST_SET_FACILITY_LOCK,
|
RIL_REQUEST_SET_FACILITY_LOCK,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
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);
|
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));
|
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,
|
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_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);
|
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) ?
|
(passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2) ?
|
||||||
RIL_REQUEST_CHANGE_SIM_PIN2 : RIL_REQUEST_CHANGE_SIM_PIN,
|
RIL_REQUEST_CHANGE_SIM_PIN2 : RIL_REQUEST_CHANGE_SIM_PIN,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
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)
|
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);
|
void ril_sim_card_remove_handler(struct ril_sim_card *sc, gulong id);
|
||||||
|
|
||||||
/* Inline wrappers */
|
/* 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)
|
ril_sim_card_app_type(struct ril_sim_card *sc)
|
||||||
{ return (sc && sc->app) ? sc->app->app_type : RIL_APPTYPE_UNKNOWN; }
|
{ 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_radio;
|
||||||
struct ril_network;
|
struct ril_network;
|
||||||
struct ril_sim_card;
|
struct ril_sim_card;
|
||||||
|
struct ril_sim_info;
|
||||||
struct ril_plugin_dbus;
|
struct ril_plugin_dbus;
|
||||||
|
|
||||||
#endif /* RIL_TYPES_H */
|
#endif /* RIL_TYPES_H */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* 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
|
* 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
|
* 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,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* 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.
|
* 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*)
|
grilio_request_append_utf8_chars(req, (char*)
|
||||||
unpacked_buf, length);
|
unpacked_buf, length);
|
||||||
grilio_queue_send_request_full(ud->q, req,
|
grilio_queue_send_request(ud->q, req,
|
||||||
RIL_REQUEST_SEND_USSD, ril_ussd_cb,
|
RIL_REQUEST_SEND_USSD);
|
||||||
ril_ussd_cbd_free,
|
|
||||||
ril_ussd_cbd_new(cb, data));
|
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
|
cb(ril_error_ok(&error), data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,14 +58,6 @@ struct netreg_data {
|
|||||||
int corestatus; /* Registration status previously reported to core */
|
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;
|
struct ofono_netreg *current_netreg;
|
||||||
|
|
||||||
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
|
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);
|
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);
|
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);
|
struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim);
|
||||||
|
|||||||
@@ -57,8 +57,6 @@
|
|||||||
#define MAX_MESSAGE_CENTER_LENGTH 255
|
#define MAX_MESSAGE_CENTER_LENGTH 255
|
||||||
#define MAX_CONTEXTS 256
|
#define MAX_CONTEXTS 256
|
||||||
#define SUSPEND_TIMEOUT 8
|
#define SUSPEND_TIMEOUT 8
|
||||||
#define MAX_MMS_MTU 1280
|
|
||||||
#define MAX_GPRS_MTU 1280
|
|
||||||
|
|
||||||
struct ofono_gprs {
|
struct ofono_gprs {
|
||||||
GSList *contexts;
|
GSList *contexts;
|
||||||
@@ -790,31 +788,6 @@ static void pri_reset_context_settings(struct pri_context *ctx)
|
|||||||
g_free(interface);
|
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)
|
static void pri_update_mms_context_settings(struct pri_context *ctx)
|
||||||
{
|
{
|
||||||
struct ofono_gprs_context *gc = ctx->context_driver;
|
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)
|
if (ctx->proxy_host)
|
||||||
pri_setproxy(settings->interface, 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)
|
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,
|
static gboolean pri_str_update(char *val, const char *newval,
|
||||||
const int maxlen)
|
const int maxlen)
|
||||||
{
|
{
|
||||||
DBG("oldval: %s, newval: %s, mmaxlen: %d", val, newval, maxlen);
|
|
||||||
|
|
||||||
if (newval) {
|
if (newval) {
|
||||||
if (strcmp(val, newval)) {
|
if (strcmp(val, newval)) {
|
||||||
strncpy(val, newval, maxlen);
|
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,
|
pri_context_signal_settings(ctx, gc->settings->ipv4 != NULL,
|
||||||
gc->settings->ipv6 != 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;
|
value = ctx->active;
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ struct ofono_netreg {
|
|||||||
struct ofono_network_registration_ops *ops;
|
struct ofono_network_registration_ops *ops;
|
||||||
int flags;
|
int flags;
|
||||||
DBusMessage *pending;
|
DBusMessage *pending;
|
||||||
|
GSList *pending_auto;
|
||||||
|
GSList *pending_list;
|
||||||
int signal_strength;
|
int signal_strength;
|
||||||
struct sim_spdi *spdi;
|
struct sim_spdi *spdi;
|
||||||
struct sim_eons *eons;
|
struct sim_eons *eons;
|
||||||
@@ -599,7 +601,7 @@ static DBusMessage *network_operator_register(DBusConnection *conn,
|
|||||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||||
return __ofono_error_access_denied(msg);
|
return __ofono_error_access_denied(msg);
|
||||||
|
|
||||||
if (netreg->pending)
|
if (netreg->pending || netreg->pending_auto || netreg->pending_list)
|
||||||
return __ofono_error_busy(msg);
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (netreg->driver->register_manual == NULL)
|
if (netreg->driver->register_manual == NULL)
|
||||||
@@ -854,6 +856,44 @@ static DBusMessage *network_get_properties(DBusConnection *conn,
|
|||||||
return reply;
|
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,
|
static DBusMessage *network_register(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -862,17 +902,19 @@ static DBusMessage *network_register(DBusConnection *conn,
|
|||||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||||
return __ofono_error_access_denied(msg);
|
return __ofono_error_access_denied(msg);
|
||||||
|
|
||||||
if (netreg->pending)
|
if (netreg->pending || netreg->pending_list)
|
||||||
return __ofono_error_busy(msg);
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (netreg->driver->register_auto == NULL)
|
if (netreg->driver->register_auto == NULL)
|
||||||
return __ofono_error_not_implemented(msg);
|
return __ofono_error_not_implemented(msg);
|
||||||
|
|
||||||
netreg->pending = dbus_message_ref(msg);
|
netreg->pending_auto = g_slist_append(netreg->pending_auto,
|
||||||
|
dbus_message_ref(msg));
|
||||||
netreg->driver->register_auto(netreg, register_callback, netreg);
|
if (!netreg->pending_auto->next) {
|
||||||
|
netreg->driver->register_auto(netreg, register_auto_callback,
|
||||||
set_registration_mode(netreg, NETWORK_REGISTRATION_MODE_AUTO);
|
netreg);
|
||||||
|
set_registration_mode(netreg, NETWORK_REGISTRATION_MODE_AUTO);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -972,26 +1014,15 @@ static void network_signal_operators_changed(struct ofono_netreg *netreg)
|
|||||||
g_dbus_send_message(conn, signal);
|
g_dbus_send_message(conn, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void operator_list_callback(const struct ofono_error *error, int total,
|
static void operator_list_reply(gpointer data, gpointer user_data)
|
||||||
const struct ofono_network_operator *list,
|
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
struct ofono_netreg *netreg = data;
|
struct ofono_netreg *netreg = user_data;
|
||||||
|
DBusMessage *msg = data;
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
DBusMessageIter array;
|
DBusMessageIter array;
|
||||||
gboolean changed;
|
|
||||||
|
|
||||||
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
reply = dbus_message_new_method_return(msg);
|
||||||
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);
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
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);
|
append_operator_struct_list(netreg, &array);
|
||||||
dbus_message_iter_close_container(&iter, &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)
|
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||||
network_signal_operators_changed(netreg);
|
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,
|
static DBusMessage *network_scan(DBusConnection *conn,
|
||||||
@@ -1024,16 +1074,17 @@ static DBusMessage *network_scan(DBusConnection *conn,
|
|||||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||||
return __ofono_error_access_denied(msg);
|
return __ofono_error_access_denied(msg);
|
||||||
|
|
||||||
if (netreg->pending)
|
if (netreg->pending || netreg->pending_auto)
|
||||||
return __ofono_error_busy(msg);
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (netreg->driver->list_operators == NULL)
|
if (netreg->driver->list_operators == NULL)
|
||||||
return __ofono_error_not_implemented(msg);
|
return __ofono_error_not_implemented(msg);
|
||||||
|
|
||||||
netreg->pending = dbus_message_ref(msg);
|
netreg->pending_list = g_slist_append(netreg->pending_list,
|
||||||
|
dbus_message_ref(msg));
|
||||||
netreg->driver->list_operators(netreg, operator_list_callback, netreg);
|
if (!netreg->pending_list->next)
|
||||||
|
netreg->driver->list_operators(netreg, operator_list_callback,
|
||||||
|
netreg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1898,6 +1949,15 @@ static void netreg_remove(struct ofono_atom *atom)
|
|||||||
if (netreg->driver != NULL && netreg->driver->remove != NULL)
|
if (netreg->driver != NULL && netreg->driver->remove != NULL)
|
||||||
netreg->driver->remove(netreg);
|
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_eons_free(netreg->eons);
|
||||||
sim_spdi_free(netreg->spdi);
|
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 */
|
/* Contents of the SIM file system, in rough initialization order */
|
||||||
char *iccid;
|
char *iccid;
|
||||||
|
struct ofono_watchlist *iccid_watches;
|
||||||
|
|
||||||
char **language_prefs;
|
char **language_prefs;
|
||||||
unsigned char *efli;
|
unsigned char *efli;
|
||||||
@@ -80,6 +81,7 @@ struct ofono_sim {
|
|||||||
char *imsi;
|
char *imsi;
|
||||||
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||||
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||||
|
struct ofono_watchlist *imsi_watches;
|
||||||
|
|
||||||
GSList *own_numbers;
|
GSList *own_numbers;
|
||||||
GSList *new_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,
|
static DBusMessage *sim_get_properties(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -380,6 +470,10 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
|
|||||||
ofono_dbus_dict_append(&dict, "SubscriberIdentity",
|
ofono_dbus_dict_append(&dict, "SubscriberIdentity",
|
||||||
DBUS_TYPE_STRING, &sim->imsi);
|
DBUS_TYPE_STRING, &sim->imsi);
|
||||||
|
|
||||||
|
if (sim->spn)
|
||||||
|
ofono_dbus_dict_append(&dict, "ServiceProviderName",
|
||||||
|
DBUS_TYPE_STRING, &sim->spn);
|
||||||
|
|
||||||
fdn = sim->fixed_dialing;
|
fdn = sim->fixed_dialing;
|
||||||
ofono_dbus_dict_append(&dict, "FixedDialing", DBUS_TYPE_BOOLEAN, &fdn);
|
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);
|
DBUS_TYPE_STRING, &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imsi_watches_notify(sim);
|
||||||
sim_set_ready(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->context = ofono_sim_context_create(sim);
|
||||||
sim->spn_watches = __ofono_watchlist_new(g_free);
|
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_read(sim->context, SIM_EFPHASE_FILEID,
|
||||||
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
||||||
@@ -2085,6 +2181,7 @@ static void sim_iccid_read_cb(int ok, int length, int record,
|
|||||||
"CardIdentifier",
|
"CardIdentifier",
|
||||||
DBUS_TYPE_STRING,
|
DBUS_TYPE_STRING,
|
||||||
&sim->iccid);
|
&sim->iccid);
|
||||||
|
iccid_watches_notify(sim);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sim_iccid_changed(int id, void *userdata)
|
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);
|
sim_spn_close(sim);
|
||||||
|
|
||||||
|
if (sim->imsi_watches) {
|
||||||
|
__ofono_watchlist_free(sim->imsi_watches);
|
||||||
|
sim->imsi_watches = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sim->context) {
|
if (sim->context) {
|
||||||
ofono_sim_context_free(sim->context);
|
ofono_sim_context_free(sim->context);
|
||||||
sim->context = NULL;
|
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,
|
static void sim_spn_set(struct ofono_sim *sim, const void *data, int length,
|
||||||
const unsigned char *dc)
|
const unsigned char *dc)
|
||||||
{
|
{
|
||||||
|
DBusConnection *conn = ofono_dbus_get_connection();
|
||||||
|
const char *path = __ofono_atom_get_path(sim->atom);
|
||||||
|
|
||||||
g_free(sim->spn);
|
g_free(sim->spn);
|
||||||
sim->spn = NULL;
|
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);
|
sim->spn_dc = g_memdup(dc, 1);
|
||||||
|
|
||||||
notify:
|
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);
|
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_modem_remove_atom_watch(modem, sim->hfp_watch);
|
||||||
|
|
||||||
|
__ofono_watchlist_free(sim->iccid_watches);
|
||||||
|
sim->iccid_watches = NULL;
|
||||||
|
|
||||||
__ofono_watchlist_free(sim->state_watches);
|
__ofono_watchlist_free(sim->state_watches);
|
||||||
sim->state_watches = NULL;
|
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);
|
ofono_modem_add_interface(modem, OFONO_SIM_MANAGER_INTERFACE);
|
||||||
sim->state_watches = __ofono_watchlist_new(g_free);
|
sim->state_watches = __ofono_watchlist_new(g_free);
|
||||||
|
sim->iccid_watches = __ofono_watchlist_new(g_free);
|
||||||
sim->simfs = sim_fs_new(sim, sim->driver);
|
sim->simfs = sim_fs_new(sim, sim->driver);
|
||||||
|
|
||||||
__ofono_atom_register(sim->atom, sim_unregister);
|
__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;
|
item->id = ++watchlist->next_id;
|
||||||
|
|
||||||
|
if (item->id == 0)
|
||||||
|
item->id = ++watchlist->next_id;
|
||||||
|
|
||||||
watchlist->items = g_slist_prepend(watchlist->items, item);
|
watchlist->items = g_slist_prepend(watchlist->items, item);
|
||||||
|
|
||||||
return item->id;
|
return item->id;
|
||||||
|
|||||||
Reference in New Issue
Block a user