[-]
[+]
|
Changed |
_service:tar_git:ofono.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:ofono.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,6 +2,6 @@
<service name="tar_git">
<param name="url">https://git.merproject.org/slava/ofono.git</param>
<param name="branch">master</param>
- <param name="revision">49b752f0</param>
+ <param name="revision">42808ed</param>
</service>
</services>
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/Makefile.am
^
|
@@ -125,6 +125,8 @@
drivers/ril/ril_call_forward.c \
drivers/ril/ril_call_settings.c \
drivers/ril/ril_call_volume.c \
+ drivers/ril/ril_cell_info.c \
+ drivers/ril/ril_cell_info_dbus.c \
drivers/ril/ril_cbs.c \
drivers/ril/ril_data.c \
drivers/ril/ril_devinfo.c \
|
[-]
[+]
|
Added |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_cell_info.c
^
|
@@ -0,0 +1,504 @@
+/*
+ * 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_cell_info.h"
+#include "ril_sim_card.h"
+#include "ril_mce.h"
+#include "ril_log.h"
+
+#include <grilio_channel.h>
+#include <grilio_request.h>
+#include <grilio_parser.h>
+
+#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
+#define DISPLAY_OFF_UPDATE_RATE (60000) /* 1 min */
+
+typedef GObjectClass RilCellInfoClass;
+typedef struct ril_cell_info RilCellInfo;
+
+struct ril_cell_info_priv {
+ GRilIoChannel *io;
+ struct ril_mce *mce;
+ struct ril_sim_card *sim_card;
+ gulong display_state_event_id;
+ gulong sim_status_event_id;
+ gboolean sim_card_ready;
+ char *log_prefix;
+ gulong event_id;
+ guint query_id;
+ guint set_rate_id;
+};
+
+enum ril_cell_info_signal {
+ SIGNAL_CELLS_CHANGED,
+ SIGNAL_COUNT
+};
+
+#define SIGNAL_CELLS_CHANGED_NAME "ril-cell-info-cells-changed"
+
+static guint ril_cell_info_signals[SIGNAL_COUNT] = { 0 };
+
+G_DEFINE_TYPE(RilCellInfo, ril_cell_info, G_TYPE_OBJECT)
+#define RIL_CELL_INFO_TYPE (ril_cell_info_get_type())
+#define RIL_CELL_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
+ RIL_CELL_INFO_TYPE, RilCellInfo))
+
+#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->priv->log_prefix, ##args)
+
+gint ril_cell_compare_location(const struct ril_cell *c1,
+ const struct ril_cell *c2)
+{
+ if (c1 && c2) {
+ if (c1->type != c2->type) {
+ return c1->type - c2->type;
+ } else if (c1->type == RIL_CELL_INFO_TYPE_GSM) {
+ const struct ril_cell_info_gsm *g1 = &c1->info.gsm;
+ const struct ril_cell_info_gsm *g2 = &c2->info.gsm;
+
+ if (g1->lac != g2->lac) {
+ return g1->lac - g2->lac;
+ } else {
+ return g1->cid - g2->cid;
+ }
+ } else if (c2->type == RIL_CELL_INFO_TYPE_WCDMA) {
+ const struct ril_cell_info_wcdma *w1 = &c1->info.wcdma;
+ const struct ril_cell_info_wcdma *w2 = &c2->info.wcdma;
+
+ if (w1->lac != w2->lac) {
+ return w1->lac - w2->lac;
+ } else {
+ return w1->cid - w2->cid;
+ }
+ } else {
+ const struct ril_cell_info_lte *l1 = &c1->info.lte;
+ const struct ril_cell_info_lte *l2 = &c2->info.lte;
+
+ GASSERT(c1->type == RIL_CELL_INFO_TYPE_LTE);
+ if (l1->ci != l2->ci) {
+ return l1->ci - l2->ci;
+ } else if (l1->pci != l2->pci) {
+ return l1->pci - l2->pci;
+ } else {
+ return l1->tac - l2->tac;
+ }
+ }
+ } else if (c1) {
+ return 1;
+ } else if (c2) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+gint ril_cell_compare_func(gconstpointer v1, gconstpointer v2)
+{
+ return ril_cell_compare_location(v1, v2);
+}
+
+static gboolean ril_cell_info_list_identical(GSList *l1, GSList *l2)
+{
+ while (l1 && l2) {
+ if (memcmp(l1->data, l2->data, sizeof(struct ril_cell))) {
+ return FALSE;
+ }
+ l1 = l1->next;
+ l2 = l2->next;
+ }
+ return !l1 && !l2;
+}
+
+static void ril_cell_info_update_cells(struct ril_cell_info *self, GSList *l)
+{
+ if (!ril_cell_info_list_identical(self->cells, l)) {
+ g_slist_free_full(self->cells, g_free);
+ self->cells = l;
+ g_signal_emit(self, ril_cell_info_signals[
+ SIGNAL_CELLS_CHANGED], 0);
+ } else {
+ g_slist_free_full(l, g_free);
+ }
+}
+
+static struct ril_cell *ril_cell_info_parse_cell_gsm(GRilIoParser *rilp,
+ gboolean registered)
+{
+ struct ril_cell *cell = g_new0(struct ril_cell, 1);
+ struct ril_cell_info_gsm *gsm = &cell->info.gsm;
+
+ if (grilio_parser_get_int32(rilp, &gsm->mcc) &&
+ grilio_parser_get_int32(rilp, &gsm->mnc) &&
+ grilio_parser_get_int32(rilp, &gsm->lac) &&
+ grilio_parser_get_int32(rilp, &gsm->cid) &&
+ grilio_parser_get_int32(rilp, &gsm->signalStrength) &&
+ grilio_parser_get_int32(rilp, &gsm->bitErrorRate)) {
+ DBG("[gsm] reg=%d,mcc=%d,mnc=%d,lac=%d,cid=%d,"
+ "strength=%d,err=%d", registered, gsm->mcc, gsm->mnc,
+ gsm->lac, gsm->cid, gsm->signalStrength,
+ gsm->bitErrorRate);
+ cell->type = RIL_CELL_INFO_TYPE_GSM;
+ cell->registered = registered;
+ return cell;
+ }
+
+ ofono_error("failed to parse GSM cell info");
+ g_free(cell);
+ return NULL;
+}
+
+static struct ril_cell *ril_cell_info_parse_cell_wcdma(GRilIoParser *rilp,
+ gboolean registered)
+{
+ struct ril_cell *cell = g_new0(struct ril_cell, 1);
+ struct ril_cell_info_wcdma *wcdma = &cell->info.wcdma;
+
+ if (grilio_parser_get_int32(rilp, &wcdma->mcc) &&
+ grilio_parser_get_int32(rilp, &wcdma->mnc) &&
+ grilio_parser_get_int32(rilp, &wcdma->lac) &&
+ grilio_parser_get_int32(rilp, &wcdma->cid) &&
+ grilio_parser_get_int32(rilp, &wcdma->psc) &&
+ grilio_parser_get_int32(rilp, &wcdma->signalStrength) &&
+ grilio_parser_get_int32(rilp, &wcdma->bitErrorRate)) {
+ DBG("[wcdma] reg=%d,mcc=%d,mnc=%d,lac=%d,cid=%d,psc=%d,"
+ "strength=%d,err=%d", registered, wcdma->mcc,
+ wcdma->mnc, wcdma->lac, wcdma->cid, wcdma->psc,
+ wcdma->signalStrength, wcdma->bitErrorRate);
+ cell->type = RIL_CELL_INFO_TYPE_WCDMA;
+ cell->registered = registered;
+ return cell;
+ }
+
+ ofono_error("failed to parse WCDMA cell info");
+ g_free(cell);
+ return NULL;
+}
+
+static struct ril_cell *ril_cell_info_parse_cell_lte(GRilIoParser *rilp,
+ gboolean registered)
+{
+ struct ril_cell *cell = g_new0(struct ril_cell, 1);
+ struct ril_cell_info_lte *lte = &cell->info.lte;
+
+ if (grilio_parser_get_int32(rilp, <e->mcc) &&
+ grilio_parser_get_int32(rilp, <e->mnc) &&
+ grilio_parser_get_int32(rilp, <e->ci) &&
+ grilio_parser_get_int32(rilp, <e->pci) &&
+ grilio_parser_get_int32(rilp, <e->tac) &&
+ grilio_parser_get_int32(rilp, <e->signalStrength) &&
|
[-]
[+]
|
Added |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_cell_info.h
^
|
@@ -0,0 +1,63 @@
+/*
+ * 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_CELL_INFO_H
+#define RIL_CELL_INFO_H
+
+#include "ril_types.h"
+
+struct ril_cell {
+ enum ril_cell_info_type type;
+ gboolean registered;
+ union {
+ struct ril_cell_info_gsm gsm;
+ struct ril_cell_info_wcdma wcdma;
+ struct ril_cell_info_lte lte;
+ } info;
+};
+
+struct ril_cell_info_priv;
+struct ril_cell_info {
+ GObject object;
+ struct ril_cell_info_priv *priv;
+ GSList *cells;
+};
+
+typedef void (*ril_cell_info_cb_t)(struct ril_cell_info *info, void *arg);
+
+gint ril_cell_compare_func(gconstpointer v1, gconstpointer v2);
+gint ril_cell_compare_location(const struct ril_cell *c1,
+ const struct ril_cell *c2);
+
+struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
+ const char *log_prefix, struct ril_mce *mce,
+ struct ril_sim_card *sim_card);
+struct ril_cell_info *ril_cell_info_ref(struct ril_cell_info *info);
+void ril_cell_info_unref(struct ril_cell_info *info);
+struct ril_cell *ril_cell_find_cell(struct ril_cell_info *info,
+ const struct ril_cell *cell);
+gulong ril_cell_info_add_cells_changed_handler(struct ril_cell_info *info,
+ ril_cell_info_cb_t cb, void *arg);
+void ril_cell_info_remove_handler(struct ril_cell_info *info, gulong id);
+
+#endif /* RIL_CELL_INFO_H */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
+ * End:
+ */
|
[-]
[+]
|
Added |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_cell_info_dbus.c
^
|
@@ -0,0 +1,546 @@
+/*
+ * 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_cell_info.h"
+#include "ril_log.h"
+
+#include <ofono/dbus.h>
+
+#include <gdbus.h>
+
+struct ril_cell_entry {
+ guint cell_id;
+ char *path;
+ struct ril_cell cell;
+};
+
+struct ril_cell_info_dbus {
+ struct ril_modem *md;
+ struct ril_cell_info *info;
+ DBusConnection *conn;
+ char *path;
+ gulong handler_id;
+ guint next_cell_id;
+ GSList *entries;
+};
+
+#define RIL_CELL_INFO_DBUS_INTERFACE "org.nemomobile.ofono.CellInfo"
+#define RIL_CELL_INFO_DBUS_CELL_ADDED_SIGNAL "CellAdded"
+#define RIL_CELL_INFO_DBUS_CELL_REMOVED_SIGNAL "CellRemoved"
+
+#define RIL_CELL_DBUS_INTERFACE_VERSION (1)
+#define RIL_CELL_DBUS_INTERFACE "org.nemomobile.ofono.Cell"
+#define RIL_CELL_DBUS_REGISTERED_CHANGED_SIGNAL "RegisteredChanged"
+#define RIL_CELL_DBUS_PROPERTY_CHANGED_SIGNAL "PropertyChanged"
+#define RIL_CELL_DBUS_REMOVED_SIGNAL "Removed"
+
+struct ril_cell_property {
+ const char *name;
+ glong off;
+ int flag;
+};
+
+#define RIL_CELL_GSM_PROPERTY(value,name) \
+ { #name, G_STRUCT_OFFSET(struct ril_cell_info_gsm,name), value }
+#define RIL_CELL_WCDMA_PROPERTY(value,name) \
+ { #name, G_STRUCT_OFFSET(struct ril_cell_info_wcdma,name), value }
+#define RIL_CELL_LTE_PROPERTY(value,name) \
+ { #name, G_STRUCT_OFFSET(struct ril_cell_info_lte,name), value }
+
+static const struct ril_cell_property ril_cell_gsm_properties [] = {
+ RIL_CELL_GSM_PROPERTY(0x01,mcc),
+ RIL_CELL_GSM_PROPERTY(0x02,mnc),
+ RIL_CELL_GSM_PROPERTY(0x04,lac),
+ RIL_CELL_GSM_PROPERTY(0x08,cid),
+ RIL_CELL_GSM_PROPERTY(0x10,signalStrength),
+ RIL_CELL_GSM_PROPERTY(0x20,bitErrorRate)
+};
+
+static const struct ril_cell_property ril_cell_wcdma_properties [] = {
+ RIL_CELL_WCDMA_PROPERTY(0x01,mcc),
+ RIL_CELL_WCDMA_PROPERTY(0x02,mnc),
+ RIL_CELL_WCDMA_PROPERTY(0x04,lac),
+ RIL_CELL_WCDMA_PROPERTY(0x08,cid),
+ RIL_CELL_WCDMA_PROPERTY(0x10,psc),
+ RIL_CELL_WCDMA_PROPERTY(0x20,signalStrength),
+ RIL_CELL_WCDMA_PROPERTY(0x40,bitErrorRate)
+};
+
+static const struct ril_cell_property ril_cell_lte_properties [] = {
+ RIL_CELL_LTE_PROPERTY(0x001,mcc),
+ RIL_CELL_LTE_PROPERTY(0x002,mnc),
+ RIL_CELL_LTE_PROPERTY(0x004,ci),
+ RIL_CELL_LTE_PROPERTY(0x008,pci),
+ RIL_CELL_LTE_PROPERTY(0x010,tac),
+ RIL_CELL_LTE_PROPERTY(0x020,signalStrength),
+ RIL_CELL_LTE_PROPERTY(0x040,rsrp),
+ RIL_CELL_LTE_PROPERTY(0x080,rsrq),
+ RIL_CELL_LTE_PROPERTY(0x100,rssnr),
+ RIL_CELL_LTE_PROPERTY(0x200,cqi),
+ RIL_CELL_LTE_PROPERTY(0x400,timingAdvance)
+};
+
+#define RIL_CELL_PROPERTY_REGISTERED 0x1000
+
+typedef void (*ril_cell_info_dbus_append_fn)(DBusMessageIter *it,
+ const struct ril_cell_entry *entry);
+
+static const char *ril_cell_info_dbus_cell_type_str(enum ril_cell_info_type t)
+{
+ switch (t) {
+ case RIL_CELL_INFO_TYPE_GSM:
+ return "gsm";
+ case RIL_CELL_INFO_TYPE_CDMA:
+ return "cdma";
+ case RIL_CELL_INFO_TYPE_LTE:
+ return "lte";
+ case RIL_CELL_INFO_TYPE_WCDMA:
+ return "wcdma";
+ case RIL_CELL_INFO_TYPE_TD_SCDMA:
+ return "tdscdma";
+ case RIL_CELL_INFO_TYPE_NONE:
+ default:
+ return "unknown";
+ }
+};
+
+static const struct ril_cell_property *ril_cell_info_dbus_cell_properties(
+ enum ril_cell_info_type type, int *count)
+{
+ switch (type) {
+ case RIL_CELL_INFO_TYPE_GSM:
+ *count = G_N_ELEMENTS(ril_cell_gsm_properties);
+ return ril_cell_gsm_properties;
+ case RIL_CELL_INFO_TYPE_WCDMA:
+ *count = G_N_ELEMENTS(ril_cell_wcdma_properties);
+ return ril_cell_wcdma_properties;
+ case RIL_CELL_INFO_TYPE_LTE:
+ *count = G_N_ELEMENTS(ril_cell_lte_properties);
+ return ril_cell_lte_properties;
+ default:
+ *count = 0;
+ return NULL;
+ }
+};
+
+static void ril_cell_info_destroy_entry(struct ril_cell_entry *entry)
+{
+ if (entry) {
+ g_free(entry->path);
+ g_free(entry);
+ }
+}
+
+static void ril_cell_info_destroy_entry_cb(gpointer data)
+{
+ ril_cell_info_destroy_entry((struct ril_cell_entry *)data);
+}
+
+static DBusMessage *ril_cell_info_dbus_reply(DBusMessage *msg,
+ const struct ril_cell_entry *entry,
+ ril_cell_info_dbus_append_fn append)
+{
+ DBusMessage *reply = dbus_message_new_method_return(msg);
+ DBusMessageIter it;
+
+ dbus_message_iter_init_append(reply, &it);
+ append(&it, entry);
+ return reply;
+}
+
+static void ril_cell_info_dbus_append_version(DBusMessageIter *it,
+ const struct ril_cell_entry *entry)
+{
+ dbus_int32_t version = RIL_CELL_DBUS_INTERFACE_VERSION;
+
+ dbus_message_iter_append_basic(it, DBUS_TYPE_INT32, &version);
+}
+
+static void ril_cell_info_dbus_append_type(DBusMessageIter *it,
+ const struct ril_cell_entry *entry)
+{
+ const char *type = ril_cell_info_dbus_cell_type_str(entry->cell.type);
+
+ dbus_message_iter_append_basic(it, DBUS_TYPE_STRING, &type);
+}
+
+static void ril_cell_info_dbus_append_registered(DBusMessageIter *it,
+ const struct ril_cell_entry *entry)
+{
+ dbus_bool_t registered = entry->cell.registered;
+
+ dbus_message_iter_append_basic(it, DBUS_TYPE_BOOLEAN, ®istered);
+}
+
+static void ril_cell_info_dbus_append_properties(DBusMessageIter *it,
+ const struct ril_cell_entry *entry)
+{
+ int i, n;
+ DBusMessageIter dict;
+ const struct ril_cell *cell = &entry->cell;
+ const struct ril_cell_property *prop =
+ ril_cell_info_dbus_cell_properties(cell->type, &n);
+
+ dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, "{sv}", &dict);
+ for (i = 0; i < n; i++) {
+ gint32 value = G_STRUCT_MEMBER(int, &cell->info, prop[i].off);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_constants.h
^
|
@@ -277,6 +277,49 @@
RIL_APPTYPE_ISIM = 5
};
+/* Cell info */
+enum ril_cell_info_type {
+ RIL_CELL_INFO_TYPE_NONE = 0,
+ RIL_CELL_INFO_TYPE_GSM = 1,
+ RIL_CELL_INFO_TYPE_CDMA = 2,
+ RIL_CELL_INFO_TYPE_LTE = 3,
+ RIL_CELL_INFO_TYPE_WCDMA = 4,
+ RIL_CELL_INFO_TYPE_TD_SCDMA = 5
+};
+
+struct ril_cell_info_gsm {
+ int mcc; /* Mobile Country Code (0..999) */
+ int mnc; /* Mobile Network Code (0..999) */
+ int lac; /* Location Area Code (0..65535) */
+ int cid; /* GSM Cell Identity (0..65535) TS 27.007 */
+ int signalStrength; /* (0-31, 99) TS 27.007 */
+ int bitErrorRate; /* (0-7, 99) TS 27.007 */
+};
+
+struct ril_cell_info_wcdma {
+ int mcc; /* Mobile Country Code (0..999) */
+ int mnc; /* Mobile Network Code (0..999) */
+ int lac; /* Location Area Code (0..65535) */
+ int cid; /* UMTS Cell Identity (0..268435455) TS 25.331 */
+ int psc; /* Primary Scrambling Code (0..511) TS 25.331) */
+ int signalStrength; /* (0-31, 99) TS 27.007 */
+ int bitErrorRate; /* (0-7, 99) TS 27.007 */
+};
+
+struct ril_cell_info_lte {
+ int mcc; /* Mobile Country Code (0..999) */
+ int mnc; /* Mobile Network Code (0..999) */
+ int ci; /* Cell Identity */
+ int pci; /* Physical cell id (0..503) */
+ int tac; /* Tracking area code */
+ int signalStrength; /* (0-31, 99) TS 27.007 8.5 */
+ int rsrp; /* Reference Signal Receive Power TS 36.133 */
+ int rsrq; /* Reference Signal Receive Quality TS 36.133 */
+ int rssnr; /* Reference Signal-to-Noise Ratio TS 36.101*/
+ int cqi; /* Channel Quality Indicator TS 36.101 */
+ int timingAdvance; /* (Distance = 300m/us) TS 36.321 */
+};
+
/* RIL Request Messages */
#define RIL_REQUEST_GET_SIM_STATUS 1
#define RIL_REQUEST_ENTER_SIM_PIN 2
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_ecclist.c
^
|
@@ -38,7 +38,7 @@
SIGNAL_COUNT
};
-#define SIGNAL_LIST_CHANGED_NAME "ril-sim-settings-imsi-changed"
+#define SIGNAL_LIST_CHANGED_NAME "ril-ecclist-changed"
static guint ril_ecclist_signals[SIGNAL_COUNT] = { 0 };
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_mce.c
^
|
@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
- * Copyright (C) 2015 Jolla Ltd.
+ * Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,116 +14,249 @@
*/
#include "ril_mce.h"
-#include "ril_constants.h"
+#include "ril_log.h"
-#include <grilio_channel.h>
-#include <grilio_request.h>
-
-#include <ofono/log.h>
#include <ofono/dbus.h>
#include <gdbus.h>
+/* <mce/dbus-names.h> */
#define MCE_SERVICE "com.nokia.mce"
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
+#define MCE_REQUEST_IF "com.nokia.mce.request"
+#define MCE_REQUEST_PATH "/com/nokia/mce/request"
+#define MCE_DISPLAY_STATUS_GET "get_display_status"
#define MCE_DISPLAY_SIG "display_status_ind"
+#define MCE_DISPLAY_DIM_STRING "dimmed"
+#define MCE_DISPLAY_ON_STRING "on"
#define MCE_DISPLAY_OFF_STRING "off"
-struct ril_mce {
+typedef GObjectClass RilMceClass;
+typedef struct ril_mce RilMce;
+
+struct ril_mce_priv {
GRilIoChannel *io;
DBusConnection *conn;
- int screen_state;
+ DBusPendingCall *req;
guint daemon_watch;
guint signal_watch;
};
-static void ril_mce_send_screen_state(struct ril_mce *mce, gboolean on)
-{
- GRilIoRequest *req = grilio_request_sized_new(8);
+enum ril_mce_signal {
+ SIGNAL_DISPLAY_STATE_CHANGED,
+ SIGNAL_COUNT
+};
- grilio_request_append_int32(req, 1); /* Number of params */
- grilio_request_append_int32(req, on); /* screen on/off */
+#define SIGNAL_DISPLAY_STATE_CHANGED_NAME "ril-mce-display-state-changed"
- grilio_channel_send_request(mce->io, req, RIL_REQUEST_SCREEN_STATE);
- grilio_request_unref(req);
+static guint ril_mce_signals[SIGNAL_COUNT] = { 0 };
+
+G_DEFINE_TYPE(RilMce, ril_mce, G_TYPE_OBJECT)
+#define RIL_MCE_TYPE (ril_mce_get_type())
+#define RIL_MCE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_MCE_TYPE,RilMce))
+
+static const char *ril_mce_display_state_string(enum ril_mce_display_state ds)
+{
+ switch (ds) {
+ case RIL_MCE_DISPLAY_OFF:
+ return MCE_DISPLAY_OFF_STRING;
+ case RIL_MCE_DISPLAY_DIM:
+ return MCE_DISPLAY_DIM_STRING;
+ case RIL_MCE_DISPLAY_ON:
+ return MCE_DISPLAY_ON_STRING;
+ default:
+ return NULL;
+ }
}
-static gboolean ril_mce_display_changed(DBusConnection *conn,
- DBusMessage *message, void *user_data)
+static enum ril_mce_display_state ril_mce_parse_display_state(DBusMessage *msg)
{
- DBusMessageIter iter;
+ DBusMessageIter it;
- if (dbus_message_iter_init(message, &iter) &&
- dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
- struct ril_mce *mce = user_data;
+ if (dbus_message_iter_init(msg, &it) &&
+ dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_STRING) {
const char *value = NULL;
- int state;
-
- dbus_message_iter_get_basic(&iter, &value);
- DBG(" %s", value);
- /* It is on if it's not off */
- state = (g_strcmp0(value, MCE_DISPLAY_OFF_STRING) != 0);
- if (mce->screen_state != state) {
- mce->screen_state = state;
- ril_mce_send_screen_state(mce, state);
+ dbus_message_iter_get_basic(&it, &value);
+ if (!g_strcmp0(value, MCE_DISPLAY_OFF_STRING)) {
+ return RIL_MCE_DISPLAY_OFF;
+ } else if (!g_strcmp0(value, MCE_DISPLAY_DIM_STRING)) {
+ return RIL_MCE_DISPLAY_DIM;
+ } else {
+ GASSERT(!g_strcmp0(value, MCE_DISPLAY_ON_STRING));
}
- } else {
- DBG("");
}
+ return RIL_MCE_DISPLAY_ON;
+}
+
+static void ril_mce_update_display_state(struct ril_mce *self,
+ enum ril_mce_display_state state)
+{
+ if (self->display_state != state) {
+ self->display_state = state;
+ g_signal_emit(self, ril_mce_signals[
+ SIGNAL_DISPLAY_STATE_CHANGED], 0);
+ }
+}
+
+static gboolean ril_mce_display_changed(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ enum ril_mce_display_state state = ril_mce_parse_display_state(msg);
+
+ DBG("%s", ril_mce_display_state_string(state));
+ ril_mce_update_display_state(RIL_MCE(user_data), state);
return TRUE;
}
+static void ril_mce_display_status_reply(DBusPendingCall *call, void *user_data)
+{
+ struct ril_mce *self = RIL_MCE(user_data);
+ struct ril_mce_priv *priv = self->priv;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ enum ril_mce_display_state state = ril_mce_parse_display_state(reply);
+
+ GASSERT(priv->req);
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(priv->req);
+ priv->req = NULL;
+
+ DBG("%s", ril_mce_display_state_string(state));
+ ril_mce_update_display_state(self, state);
+}
+
static void ril_mce_connect(DBusConnection *conn, void *user_data)
{
- struct ril_mce *mce = user_data;
+ struct ril_mce *self = RIL_MCE(user_data);
+ struct ril_mce_priv *priv = self->priv;
DBG("");
- if (!mce->signal_watch) {
- mce->signal_watch = g_dbus_add_signal_watch(conn,
+ if (!priv->req) {
+ DBusMessage *msg = dbus_message_new_method_call(MCE_SERVICE,
+ MCE_REQUEST_PATH, MCE_REQUEST_IF,
+ MCE_DISPLAY_STATUS_GET);
+ if (g_dbus_send_message_with_reply(conn, msg, &priv->req, -1)) {
+ dbus_pending_call_set_notify(priv->req,
+ ril_mce_display_status_reply,
+ self, NULL);
+ dbus_message_unref(msg);
+ }
+ }
+ if (!priv->signal_watch) {
+ priv->signal_watch = g_dbus_add_signal_watch(conn,
MCE_SERVICE, NULL, MCE_SIGNAL_IF, MCE_DISPLAY_SIG,
- ril_mce_display_changed, mce, NULL);
+ ril_mce_display_changed, self, NULL);
}
}
static void ril_mce_disconnect(DBusConnection *conn, void *user_data)
{
- struct ril_mce *mce = user_data;
+ struct ril_mce *self = user_data;
+ struct ril_mce_priv *priv = self->priv;
+
+ DBG("");
+ if (priv->signal_watch) {
+ g_dbus_remove_watch(conn, priv->signal_watch);
+ priv->signal_watch = 0;
+ }
+ if (priv->req) {
+ dbus_pending_call_cancel(priv->req);
+ dbus_pending_call_unref(priv->req);
+ }
+}
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_mce.h
^
|
@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
- * Copyright (C) 2015 Jolla Ltd.
+ * Copyright (C) 2015-2016 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -18,8 +18,27 @@
#include "ril_types.h"
-struct ril_mce *ril_mce_new(GRilIoChannel *io);
-void ril_mce_free(struct ril_mce *mce);
+enum ril_mce_display_state {
+ RIL_MCE_DISPLAY_OFF,
+ RIL_MCE_DISPLAY_DIM,
+ RIL_MCE_DISPLAY_ON
+};
+
+struct ril_mce_priv;
+struct ril_mce {
+ GObject object;
+ struct ril_mce_priv *priv;
+ enum ril_mce_display_state display_state;
+};
+
+struct ril_mce *ril_mce_new(void);
+struct ril_mce *ril_mce_ref(struct ril_mce *mce);
+void ril_mce_unref(struct ril_mce *mce);
+
+typedef void (*ril_mce_cb_t)(struct ril_mce *mce, void *arg);
+gulong ril_mce_add_display_state_changed_handler(struct ril_mce *mce,
+ ril_mce_cb_t cb, void *arg);
+void ril_mce_remove_handler(struct ril_mce *mce, gulong id);
#endif /* RIL_MCE_H */
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_phonebook.c
^
|
@@ -1,7 +1,13 @@
/*
- * oFono - Open Source Telephony - RIL-based devices
*
- * Copyright (C) 2015 Jolla Ltd.
+ * oFono - Open Source Telephony - RIL Modem Support
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) ST-Ericsson SA 2010.
+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
+ * Copyright (C) 2013 Jolla Ltd
+ * Contact: Jussi Kangas <jussi.kangas@tieto.com>
+ * Copyright (C) 2014 Canonical 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
@@ -11,42 +17,65 @@
* 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
*/
#include "ril_plugin.h"
-#include "ril_util.h"
-#include "ril_log.h"
-#include "ril_constants.h"
-#include "util.h"
+#include <ofono.h>
+
#include "simutil.h"
+#include "util.h"
+
+struct cb_data {
+ void *cb;
+ void *data;
+ void *user;
+};
+
+static inline struct cb_data *cb_data_new(void *cb, void *data, void *user)
+{
+ struct cb_data *ret;
+
+ ret = g_new0(struct cb_data, 1);
+ ret->cb = cb;
+ ret->data = data;
+ ret->user = user;
+
+ return ret;
+}
+
+#define CALLBACK_WITH_FAILURE(cb, args...) \
+ do { \
+ struct ofono_error cb_e; \
+ cb_e.type = OFONO_ERROR_TYPE_FAILURE; \
+ cb_e.error = 0; \
+ \
+ cb(&cb_e, ##args); \
+ } while (0) \
-/* File info parameters */
-#define FCP_TEMPLATE 0x62
-#define FCP_FILE_SIZE 0x80
-#define FCP_FILE_DESC 0x82
-#define FCP_FILE_ID 0x83
-#define FCP_FILE_LIFECYCLE 0x8A
-#define FCP_FILE_SECURITY_ARR 0x8B
-#define FCP_FILE_SECURITY_COMPACT 0x8C
-#define FCP_FILE_SECURITY_EXPANDED 0xAB
-
-#define SIM_EFPBR_FILEID 0x4F30
-
-#define UNUSED 0xff
-
-#define EXT1_CP_SUBADDRESS 1
-#define EXT1_ADDITIONAL_DATA 2
-
-#define NAME_SIZE 64
-#define NUMBER_SIZE 256
-#define EMAIL_SIZE 128
-#define EXT_NUMBER_SIZE 24
-#define SNE_SIZE 64
+#define CALLBACK_WITH_SUCCESS(f, args...) \
+ do { \
+ struct ofono_error e; \
+ e.type = OFONO_ERROR_TYPE_NO_ERROR; \
+ e.error = 0; \
+ f(&e, ##args); \
+ } while (0)
+
+#define SIM_EFPBR_FILEID 0x4F30
+
+#define UNUSED 0xFF
+
+#define EXT1_CP_SUBADDRESS 1
+#define EXT1_ADDITIONAL_DATA 2
/* TON (Type Of Number) See TS 24.008 */
-#define TON_MASK 0x70
-#define TON_INTERNATIONAL 0x10
+#define TON_MASK 0x70
+#define TON_INTERNATIONAL 0x10
enum constructed_tag {
TYPE_1_TAG = 0xA8,
@@ -56,7 +85,7 @@
enum file_type_tag {
TYPE_ADN = 0xC0,
- TYPE_IAD = 0xC1,
+ TYPE_IAP = 0xC1,
TYPE_EXT1 = 0xC2,
TYPE_SNE = 0xC3,
TYPE_ANR = 0xC4,
@@ -69,17 +98,25 @@
TYPE_CCP1 = 0xCB
};
-struct ril_phonebook_file {
+struct pb_file_info {
+ enum constructed_tag pbr_type;
int file_id;
- guchar file_type;
- guchar structure;
+ enum file_type_tag file_type;
int file_length;
int record_length;
+};
+
+struct record_to_read {
+ int file_id;
+ enum file_type_tag type_tag;
+ int record_length;
int record;
- gboolean handled;
+ int adn_idx;
+ gboolean anr_ext; /* Is it an EXT1 record for ANR? */
+ gboolean set_by_iap; /* Type 2 file? */
};
-struct ril_phonebook_entry {
+struct phonebook_entry {
int entry;
char *name;
char *number;
@@ -88,773 +125,833 @@
char *sne;
};
-struct ril_phonebook {
- int refcount;
- GRilIoQueue *q;
- struct ril_modem *modem;
- struct ofono_phonebook *pb;
- guint timer_id;
-};
+static unsigned char sim_path[] = { 0x3F, 0x00, 0x7F, 0x10 };
+static unsigned char usim_path[] = { 0x3F, 0x00, 0x7F, 0x10, 0x5F, 0x3A };
-struct ril_phonebook_export {
- struct ril_phonebook *pbd;
- int app_type;
- ofono_phonebook_cb_t cb;
- gpointer data;
- gint pb_entry;
- struct ril_phonebook_file ref_file_info;
- struct ril_phonebook_file *ext_file_info;
- struct ril_phonebook_file *extension_file_info; /* NEEDED? */
- struct ril_phonebook_file *current_file_info;
- GSList *pb_files;
- GSList *pb_next;
- GSList *pb_entries;
- guchar ext1_to_type;
- guchar ext1_to_entry;
-};
+/*
+ * Table for BCD to utf8 conversion. See table 4.4 in TS 31.102.
+ * BCD 0x0C indicates pause before sending following digits as DTMF tones.
+ * BCD 0x0D is a wildcard that means "any digit". These values are mapped to
+ * ',' and '?', following the Android/iPhone convention for the first and Nokia
+ * convention for the second (only OEM that I have seen that supports this
+ * feature). BCD 0x0E is reserved, we convert it to 'r'.
+ */
+static const char digit_to_utf8[] = "0123456789*#,?r\0";
-static const guchar sim_path[4] = {0x3F, 0x00, 0x7F, 0x10};
-static const guchar usim_path[6] = {0x3F, 0x00, 0x7F, 0x10, 0x5F, 0x3A};
+/* One of these for each record in EF_PBR */
+struct pb_ref_rec {
+ GSList *pb_files; /* File ids to read (pb_file_info nodes) */
+ GSList *pb_next; /* Next file info to read */
+ GSList *pending_records; /* List of record_to_read */
+ GSList *next_record; /* Next record_to_read to process */
+ GTree *phonebook; /* Container of phonebook_entry structures */
+};
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_plugin.c
^
|
@@ -17,6 +17,7 @@
#include "ril_sim_card.h"
#include "ril_sim_info.h"
#include "ril_sim_settings.h"
+#include "ril_cell_info.h"
#include "ril_network.h"
#include "ril_radio.h"
#include "ril_data.h"
@@ -83,6 +84,9 @@
struct ril_plugin pub;
struct ril_plugin_dbus *dbus;
struct ril_data_manager *data_manager;
+ struct ril_mce *mce;
+ gboolean display_on;
+ gulong display_state_change_id;
GSList *slots;
ril_slot_info_ptr *slots_info;
struct ril_slot *voice_slot;
@@ -116,6 +120,8 @@
struct ril_sim_info *sim_info;
struct ril_sim_info_dbus *sim_info_dbus;
struct ril_sim_settings *sim_settings;
+ struct ril_cell_info *cell_info;
+ struct ril_cell_info_dbus *cell_info_dbus;
struct ril_data *data;
GRilIoChannel *io;
gulong io_event_id[IO_EVENT_COUNT];
@@ -187,6 +193,29 @@
g_slist_foreach(plugin->slots, ril_plugin_foreach_slot_proc, fn);
}
+static void ril_plugin_send_screen_state(struct ril_slot *slot)
+{
+ if (slot->io) {
+ GRilIoRequest *req = grilio_request_sized_new(8);
+ grilio_request_append_int32(req, 1); /* Number of params */
+ grilio_request_append_int32(req, slot->plugin->display_on);
+ grilio_channel_send_request(slot->io, req,
+ RIL_REQUEST_SCREEN_STATE);
+ grilio_request_unref(req);
+ }
+}
+
+static void ril_plugin_display_state_cb(struct ril_mce *mce, void *user_data)
+{
+ struct ril_plugin_priv *plugin = user_data;
+ const gboolean display_was_on = plugin->display_on;
+
+ plugin->display_on = (mce->display_state != RIL_MCE_DISPLAY_OFF);
+ if (plugin->display_on != display_was_on) {
+ ril_plugin_foreach_slot(plugin, ril_plugin_send_screen_state);
+ }
+}
+
static void ril_plugin_remove_slot_handler(struct ril_slot *slot, int id)
{
GASSERT(id >= 0 && id<IO_EVENT_COUNT);
@@ -233,16 +262,16 @@
GASSERT(!slot->sim_watch_id);
if (kill_io) {
- if (slot->mce) {
- ril_mce_free(slot->mce);
- slot->mce = NULL;
- }
-
if (slot->retry_id) {
g_source_remove(slot->retry_id);
slot->retry_id = 0;
}
+ if (slot->cell_info) {
+ ril_cell_info_unref(slot->cell_info);
+ slot->cell_info = NULL;
+ }
+
if (slot->data) {
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
ril_data_unref(slot->data);
@@ -648,6 +677,11 @@
slot->sim_info_dbus = NULL;
}
+ if (slot->cell_info_dbus) {
+ ril_cell_info_dbus_free(slot->cell_info_dbus);
+ slot->cell_info_dbus = NULL;
+ }
+
slot->modem = NULL;
ril_radio_set_online(slot->radio, FALSE);
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
@@ -768,6 +802,11 @@
slot->sim_info_dbus = ril_sim_info_dbus_new(slot->modem,
slot->sim_info);
+ if (slot->cell_info) {
+ slot->cell_info_dbus =
+ ril_cell_info_dbus_new(slot->modem,
+ slot->cell_info);
+ }
ril_modem_set_removed_cb(modem, ril_plugin_modem_removed, slot);
ril_modem_set_online_cb(modem, ril_plugin_modem_online, slot);
@@ -849,9 +888,6 @@
GASSERT(slot->io->connected);
GASSERT(!slot->io_event_id[IO_EVENT_CONNECTED]);
- GASSERT(!slot->mce);
- slot->mce = ril_mce_new(slot->io);
-
GASSERT(!slot->imei_req_id);
slot->imei_req_id = grilio_channel_send_request_full(slot->io, NULL,
RIL_REQUEST_GET_IMEI, ril_plugin_imei_cb, NULL, slot);
@@ -879,6 +915,12 @@
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
slot->radio, slot->network, slot->io);
+ GASSERT(!slot->cell_info);
+ if (slot->io->ril_version > 8) {
+ slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
+ plugin->mce, slot->sim_card);
+ }
+
if (ril_plugin_can_create_modem(slot) && !slot->modem) {
ril_plugin_create_modem(slot);
}
@@ -1508,6 +1550,9 @@
ril_plugin_init_slots(ril_plugin);
ril_plugin->dbus = ril_plugin_dbus_new(&ril_plugin->pub);
ril_plugin->data_manager = ril_data_manager_new(ps.dm_flags);
+ ril_plugin->mce = ril_mce_new();
+ ril_plugin->display_on =
+ (ril_plugin->mce->display_state != RIL_MCE_DISPLAY_OFF);
if (ril_plugin->slots) {
/*
@@ -1576,6 +1621,12 @@
*/
ril_plugin_foreach_slot(ril_plugin, ril_plugin_init_io);
+ /* Set initial screen state and register for updates */
+ ril_plugin_foreach_slot(ril_plugin, ril_plugin_send_screen_state);
+ ril_plugin->display_state_change_id =
+ ril_mce_add_display_state_changed_handler(ril_plugin->mce,
+ ril_plugin_display_state_cb, ril_plugin);
+
/* This will set 'ready' flag if we have no modems at all */
ril_plugin_update_ready(ril_plugin);
return 0;
@@ -1609,6 +1660,9 @@
g_slist_free_full(ril_plugin->slots, ril_plugin_destroy_slot);
ril_plugin_dbus_free(ril_plugin->dbus);
ril_data_manager_unref(ril_plugin->data_manager);
+ ril_mce_remove_handler(ril_plugin->mce,
+ ril_plugin->display_state_change_id);
+ ril_mce_unref(ril_plugin->mce);
g_key_file_free(ril_plugin->storage);
g_free(ril_plugin->slots_info);
g_free(ril_plugin->default_voice_imsi);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_plugin.h
^
|
@@ -104,6 +104,11 @@
struct ril_sim_info *info);
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus);
+struct ril_cell_info_dbus;
+struct ril_cell_info_dbus *ril_cell_info_dbus_new(struct ril_modem *md,
+ struct ril_cell_info *info);
+void ril_cell_info_dbus_free(struct ril_cell_info_dbus *dbus);
+
struct ril_plugin_dbus;
struct ril_plugin_dbus *ril_plugin_dbus_new(struct ril_plugin *plugin);
void ril_plugin_dbus_free(struct ril_plugin_dbus *dbus);
@@ -132,19 +137,6 @@
#define ril_modem_slot(modem) ((modem)->config.slot)
#define ril_modem_io(modem) ((modem)->io)
-void ril_sim_read_file_linear(struct ofono_sim *sim, int fileid,
- int record, int length, const unsigned char *path,
- unsigned int path_len, ofono_sim_read_cb_t cb, void *data);
-void ril_sim_read_file_cyclic(struct ofono_sim *sim, int fileid,
- int record, int length, const unsigned char *path,
- unsigned int path_len, ofono_sim_read_cb_t cb, void *data);
-void ril_sim_read_file_transparent(struct ofono_sim *sim, int fileid,
- int start, int length, const unsigned char *path,
- unsigned int path_len, ofono_sim_read_cb_t cb, void *data);
-void ril_sim_read_file_info(struct ofono_sim *sim, int fileid,
- const unsigned char *path, unsigned int path_len,
- ofono_sim_file_info_cb_t cb, void *data);
-
int ril_sim_app_type(struct ofono_sim *sim);
int ril_netreg_check_if_really_roaming(struct ofono_netreg *netreg, gint status);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_sim.c
^
|
@@ -67,7 +67,6 @@
struct ril_sim {
GRilIoChannel *io;
GRilIoQueue *q;
- GRilIoQueue *q2;
GList *pin_cbd_list;
struct ofono_sim *sim;
struct ril_sim_card *card;
@@ -386,12 +385,14 @@
return id;
}
-static void ril_sim_internal_read_file_info(struct ril_sim *sd, GRilIoQueue *q,
- int fileid, const unsigned char *path, unsigned int path_len,
+static void ril_sim_ofono_read_file_info(struct ofono_sim *sim, int fileid,
+ const unsigned char *path, unsigned int len,
ofono_sim_file_info_cb_t cb, void *data)
{
- if (!sd || !ril_sim_request_io(sd, q, fileid, CMD_GET_RESPONSE,
- 0, 0, 15, path, path_len, ril_sim_file_info_cb,
+ struct ril_sim *sd = ril_sim_get_data(sim);
+
+ if (!sd || !ril_sim_request_io(sd, sd->q, fileid, CMD_GET_RESPONSE,
+ 0, 0, 15, path, len, ril_sim_file_info_cb,
ril_sim_cbd_new(sd, cb, data))) {
struct ofono_error error;
cb(ril_error_failure(&error), -1, -1, -1, NULL,
@@ -399,25 +400,6 @@
}
}
-static void ril_sim_ofono_read_file_info(struct ofono_sim *sim, int fileid,
- const unsigned char *path, unsigned int len,
- ofono_sim_file_info_cb_t cb, void *data)
-{
- struct ril_sim *sd = ril_sim_get_data(sim);
-
- ril_sim_internal_read_file_info(sd, sd->q, fileid, path, len, cb, data);
-}
-
-void ril_sim_read_file_info(struct ofono_sim *sim, int fileid,
- const unsigned char *path, unsigned int path_len,
- ofono_sim_file_info_cb_t cb, void *data)
-{
- struct ril_sim *sd = ril_sim_get_data(sim);
-
- ril_sim_internal_read_file_info(sd, sd->q2, fileid, path, path_len,
- cb, data);
-}
-
static void ril_sim_read_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
@@ -458,42 +440,14 @@
}
}
-static inline void ril_sim_internal_read_file_transparent(struct ril_sim *sd,
- GRilIoQueue *q, int fileid, int start, int length,
- const unsigned char *path, unsigned int path_len,
- ofono_sim_read_cb_t cb, void *data)
-{
- ril_sim_read(sd, q, fileid, CMD_READ_BINARY, (start >> 8),
- (start & 0xff), length, path, path_len, cb, data);
-}
-
static void ril_sim_ofono_read_file_transparent(struct ofono_sim *sim,
int fileid, int start, int length, const unsigned char *path,
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
- ril_sim_internal_read_file_transparent(sd, sd->q, fileid, start, length,
- path, path_len, cb, data);
-}
-
-void ril_sim_read_file_transparent(struct ofono_sim *sim, int fileid,
- int start, int length, const unsigned char *path,
- unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
-{
- struct ril_sim *sd = ril_sim_get_data(sim);
-
- ril_sim_internal_read_file_transparent(sd, sd->q2, fileid, start,
- length, path, path_len, cb, data);
-}
-
-static inline void ril_sim_internal_read_file_linear(struct ril_sim *sd,
- GRilIoQueue *q, int fileid, int record, int length,
- const unsigned char *path, unsigned int path_len,
- ofono_sim_read_cb_t cb, void *data)
-{
- ril_sim_read(sd, q, fileid, CMD_READ_RECORD, record, 4, length,
- path, path_len, cb, data);
+ ril_sim_read(sd, sd->q, fileid, CMD_READ_BINARY, (start >> 8),
+ (start & 0xff), length, path, path_len, cb, data);
}
static void ril_sim_ofono_read_file_linear(struct ofono_sim *sim, int fileid,
@@ -502,29 +456,10 @@
{
struct ril_sim *sd = ril_sim_get_data(sim);
- ril_sim_internal_read_file_linear(sd, sd->q, fileid, record, length,
- path, path_len, cb, data);
-}
-
-void ril_sim_read_file_linear(struct ofono_sim *sim, int fileid,
- int record, int length, const unsigned char *path,
- unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
-{
- struct ril_sim *sd = ril_sim_get_data(sim);
-
- ril_sim_internal_read_file_linear(sd, sd->q2, fileid, record, length,
+ ril_sim_read(sd, sd->q, fileid, CMD_READ_RECORD, record, 4, length,
path, path_len, cb, data);
}
-void ril_sim_read_file_cyclic(struct ofono_sim *sim, int fileid,
- int rec, int length, const unsigned char *path,
- unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
-{
- /* Hmmm... Is this right? */
- ril_sim_read_file_linear(sim, fileid, rec, length, path, path_len,
- cb, data);
-}
-
static void ril_sim_ofono_read_file_cyclic(struct ofono_sim *sim, int fileid,
int rec, int length, const unsigned char *path,
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
@@ -1045,18 +980,7 @@
sd->slot = ril_modem_slot(modem);
sd->io = grilio_channel_ref(ril_modem_io(modem));
sd->card = ril_sim_card_ref(modem->sim_card);
-
- /* NB: One queue is used for the requests originated from the ofono
- * core, and the second one if for the requests initiated internally
- * by the RIL code.
- *
- * The difference is that when SIM card is removed, ofono requests
- * are cancelled without invoking the completion callbacks (otherwise
- * ofono would crash) while our completion callbacks have to be
- * notified in this case (otherwise we would leak memory)
- */
sd->q = grilio_queue_new(sd->io);
- sd->q2 = grilio_queue_new(sd->io);
DBG("[%u]", sd->slot);
@@ -1077,7 +1001,6 @@
DBG("[%u]", sd->slot);
g_list_free_full(sd->pin_cbd_list, ril_sim_pin_cbd_list_free_cb);
grilio_queue_cancel_all(sd->q, FALSE);
- grilio_queue_cancel_all(sd->q2, TRUE);
ofono_sim_set_data(sim, NULL);
if (sd->idle_id) {
@@ -1093,7 +1016,6 @@
grilio_channel_unref(sd->io);
grilio_queue_unref(sd->q);
- grilio_queue_unref(sd->q2);
g_free(sd);
}
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_sim_info_dbus.c
^
|
@@ -205,7 +205,7 @@
return dbus;
} else {
- ofono_error("RIL D-Bus register failed");
+ ofono_error("CellInfo D-Bus register failed");
ril_sim_info_dbus_free(dbus);
return NULL;
}
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_sms.c
^
|
@@ -28,7 +28,7 @@
#define TYPE_LOCAL 129
#define TYPE_INTERNATIONAL 145
-static unsigned char path[4] = {0x3F, 0x00, 0x7F, 0x10};
+static unsigned char sim_path[4] = {0x3F, 0x00, 0x7F, 0x10};
enum ril_sms_events {
SMS_EVENT_NEW_SMS,
@@ -42,6 +42,7 @@
GRilIoQueue *q;
struct ril_modem *modem;
struct ofono_sms *sms;
+ struct ofono_sim_context *sim_context;
gulong event_id[SMS_EVENT_COUNT];
guint timer_id;
};
@@ -366,11 +367,10 @@
grilio_request_unref(req);
}
-static void ril_sms_on_sim_cb(const struct ofono_error *error,
- const unsigned char *sdata,
- int length, void *data)
+static void ril_sms_on_sim_cb(int ok, int total_length, int record,
+ const unsigned char *sdata, int length, void *userdata)
{
- struct ril_sms_on_sim_req *cbd = data;
+ struct ril_sms_on_sim_req *cbd = userdata;
struct ril_sms *sd = cbd->sd;
/*
@@ -383,7 +383,7 @@
* the read length to take into account this read octet in order
* to calculate the proper tpdu length.
*/
- if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
+ if (ok) {
unsigned int smsc_len = sdata[1] + 1;
ofono_sms_deliver_notify(sd->sms, sdata + 1, length - 1,
length - smsc_len - 1);
@@ -409,10 +409,15 @@
grilio_parser_get_int32(&rilp, &data_len) && data_len > 0 &&
grilio_parser_get_int32(&rilp, &rec)) {
DBG("rec %d", rec);
- ril_sim_read_file_linear(sim, SIM_EFSMS_FILEID, rec,
- EFSMS_LENGTH, path, sizeof(path),
- ril_sms_on_sim_cb,
- ril_sms_on_sim_req_new(sd,rec));
+ if (sd->sim_context) {
+ ofono_sim_read_record(sd->sim_context,
+ SIM_EFSMS_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_FIXED,
+ rec, EFSMS_LENGTH,
+ sim_path, sizeof(sim_path),
+ ril_sms_on_sim_cb,
+ ril_sms_on_sim_req_new(sd,rec));
+ }
}
}
@@ -444,14 +449,18 @@
void *data)
{
struct ril_modem *modem = data;
+ struct ofono_sim *sim = ril_modem_ofono_sim(modem);
struct ril_sms *sd = g_new0(struct ril_sms, 1);
sd->modem = modem;
sd->sms = sms;
sd->io = grilio_channel_ref(ril_modem_io(modem));
+ sd->sim_context = ofono_sim_context_create(sim);
sd->q = grilio_queue_new(sd->io);
sd->timer_id = g_idle_add(ril_sms_register, sd);
ofono_sms_set_data(sms, sd);
+
+ GASSERT(sd->sim_context);
return 0;
}
@@ -463,6 +472,10 @@
DBG("");
ofono_sms_set_data(sms, NULL);
+ if (sd->sim_context) {
+ ofono_sim_context_free(sd->sim_context);
+ }
+
for (i=0; i<G_N_ELEMENTS(sd->event_id); i++) {
grilio_channel_remove_handler(sd->io, sd->event_id[i]);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/drivers/ril/ril_types.h
^
|
@@ -39,6 +39,7 @@
#define RIL_RETRY_SECS (2)
#define RIL_RETRY_MS (RIL_RETRY_SECS*1000)
+struct ril_mce;
struct ril_data;
struct ril_modem;
struct ril_radio;
@@ -46,6 +47,7 @@
struct ril_sim_card;
struct ril_sim_info;
struct ril_sim_settings;
+struct ril_cell_info;
struct ril_slot_config {
guint slot;
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/include/sim.h
^
|
@@ -104,6 +104,11 @@
typedef void (*ofono_sim_file_read_cb_t)(int ok, int total_length, int record,
const unsigned char *data,
int record_length, void *userdata);
+
+typedef void (*ofono_sim_read_info_cb_t)(int ok, unsigned char file_status,
+ int total_length, int record_length,
+ void *userdata);
+
typedef void (*ofono_sim_file_changed_cb_t)(int id, void *userdata);
typedef void (*ofono_sim_file_write_cb_t)(int ok, void *userdata);
@@ -247,6 +252,22 @@
enum ofono_sim_file_structure expected,
ofono_sim_file_read_cb_t cb, void *data);
+int ofono_sim_read_path(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ const unsigned char *path, unsigned int path_len,
+ ofono_sim_file_read_cb_t cb, void *data);
+
+int ofono_sim_read_info(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ const unsigned char *path, unsigned int pth_len,
+ ofono_sim_read_info_cb_t cb, void *data);
+
+int ofono_sim_read_record(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ int record, int record_length,
+ const unsigned char *path, unsigned int pth_len,
+ ofono_sim_file_read_cb_t cb, void *data);
+
int ofono_sim_write(struct ofono_sim_context *context, int id,
ofono_sim_file_write_cb_t cb,
enum ofono_sim_file_structure structure, int record,
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/src/phonebook.c
^
|
@@ -53,7 +53,7 @@
};
struct ofono_phonebook {
- DBusMessage *pending;
+ GSList *pending;
int storage_index; /* go through all supported storage */
int flags;
GString *vcards; /* entries with vcard 3.0 format */
@@ -431,9 +431,24 @@
return;
}
+static void phonebook_reply(gpointer data, gpointer user_data)
+{
+ DBusMessage *msg = data;
+ struct ofono_phonebook *phonebook = user_data;
+ DBusMessage *reply = generate_export_entries_reply(phonebook, msg);
+
+ __ofono_dbus_pending_reply(&msg, reply);
+}
+
+static void phonebook_cancel(gpointer data)
+{
+ DBusMessage *msg = data;
+
+ __ofono_dbus_pending_reply(&msg, __ofono_error_canceled(msg));
+}
+
static void export_phonebook(struct ofono_phonebook *phonebook)
{
- DBusMessage *reply;
const char *pb = storage_support[phonebook->storage_index];
if (pb) {
@@ -442,13 +457,9 @@
return;
}
- reply = generate_export_entries_reply(phonebook, phonebook->pending);
- if (reply == NULL) {
- dbus_message_unref(phonebook->pending);
- return;
- }
-
- __ofono_dbus_pending_reply(&phonebook->pending, reply);
+ g_slist_foreach(phonebook->pending, phonebook_reply, phonebook);
+ g_slist_free(phonebook->pending);
+ phonebook->pending = NULL;
phonebook->flags |= PHONEBOOK_FLAG_CACHED;
}
@@ -458,23 +469,22 @@
struct ofono_phonebook *phonebook = data;
DBusMessage *reply;
- if (phonebook->pending) {
- reply = __ofono_error_busy(phonebook->pending);
- g_dbus_send_message(conn, reply);
- return NULL;
- }
-
if (phonebook->flags & PHONEBOOK_FLAG_CACHED) {
reply = generate_export_entries_reply(phonebook, msg);
g_dbus_send_message(conn, reply);
return NULL;
}
- g_string_set_size(phonebook->vcards, 0);
- phonebook->storage_index = 0;
-
- phonebook->pending = dbus_message_ref(msg);
- export_phonebook(phonebook);
+ if (phonebook->pending) {
+ phonebook->pending = g_slist_append(phonebook->pending,
+ dbus_message_ref(msg));
+ } else {
+ phonebook->pending = g_slist_append(NULL,
+ dbus_message_ref(msg));
+ g_string_set_size(phonebook->vcards, 0);
+ phonebook->storage_index = 0;
+ export_phonebook(phonebook);
+ }
return NULL;
}
@@ -516,6 +526,11 @@
DBusConnection *conn = ofono_dbus_get_connection();
struct ofono_modem *modem = __ofono_atom_get_modem(pb->atom);
+ if (pb->pending) {
+ g_slist_free_full(pb->pending, phonebook_cancel);
+ pb->pending = NULL;
+ }
+
ofono_modem_remove_interface(modem, OFONO_PHONEBOOK_INTERFACE);
g_dbus_unregister_interface(conn, path, OFONO_PHONEBOOK_INTERFACE);
}
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/src/sim.c
^
|
@@ -1710,7 +1710,7 @@
if (sim_sst_is_active(sim->efsst, sim->efsst_length,
SIM_SST_SERVICE_BDN)) {
sim_fs_read_info(sim->context, SIM_EFBDN_FILEID,
- OFONO_SIM_FILE_STRUCTURE_FIXED,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, NULL, 0,
sim_efbdn_info_read_cb, sim);
return TRUE;
}
@@ -1764,7 +1764,7 @@
if (sim_sst_is_active(sim->efsst, sim->efsst_length,
SIM_SST_SERVICE_FDN)) {
sim_fs_read_info(sim->context, SIM_EFADN_FILEID,
- OFONO_SIM_FILE_STRUCTURE_FIXED,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, NULL, 0,
sim_efadn_info_read_cb, sim);
return;
}
@@ -2314,6 +2314,34 @@
return sim_fs_read(context, id, expected_type, 0, 0, NULL, 0, cb, data);
}
+int ofono_sim_read_path(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ const unsigned char *path, unsigned int path_len,
+ ofono_sim_file_read_cb_t cb, void *data)
+{
+ return sim_fs_read(context, id, expected_type, 0, 0,
+ path, path_len, cb, data);
+}
+
+int ofono_sim_read_info(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ const unsigned char *path, unsigned int pth_len,
+ ofono_sim_read_info_cb_t cb, void *data)
+{
+ return sim_fs_read_info(context, id, expected_type, path, pth_len,
+ cb, data);
+}
+
+int ofono_sim_read_record(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ int record, int record_length,
+ const unsigned char *path, unsigned int pth_len,
+ ofono_sim_file_read_cb_t cb, void *data)
+{
+ return sim_fs_read_record(context, id, expected_type, record,
+ record_length, path, pth_len, cb, data);
+}
+
int ofono_sim_write(struct ofono_sim_context *context, int id,
ofono_sim_file_write_cb_t cb,
enum ofono_sim_file_structure structure, int record,
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/src/simfs.c
^
|
@@ -264,7 +264,7 @@
}
if (op->info_only == TRUE)
- ((sim_fs_read_info_cb_t) op->cb)
+ ((ofono_sim_read_info_cb_t) op->cb)
(0, 0, 0, 0, op->userdata);
else if (op->is_read == TRUE)
((ofono_sim_file_read_cb_t) op->cb)
@@ -335,6 +335,27 @@
sim_fs_end_current(fs);
}
+static void sim_fs_op_read_record_cb(const struct ofono_error *error,
+ const unsigned char *sdata, int length,
+ void *data)
+{
+ struct sim_fs *fs = data;
+ struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
+ ofono_sim_file_read_cb_t cb = op->cb;
+
+ if (cb == NULL) {
+ sim_fs_end_current(fs);
+ return;
+ }
+
+ if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
+ cb(1, -1, op->current, sdata, length, op->userdata);
+ else
+ cb(0, -1, op->current, NULL, 0, op->userdata);
+
+ sim_fs_end_current(fs);
+}
+
static void sim_fs_op_read_block_cb(const struct ofono_error *error,
const unsigned char *data, int len,
void *user)
@@ -565,7 +586,8 @@
driver->read_file_linear(fs->sim, op->id, op->current,
op->record_length,
- NULL, 0,
+ op->path_len ? op->path : NULL,
+ op->path_len,
sim_fs_op_retrieve_cb, fs);
break;
case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
@@ -576,7 +598,8 @@
driver->read_file_cyclic(fs->sim, op->id, op->current,
op->record_length,
- NULL, 0,
+ op->path_len ? op->path : NULL,
+ op->path_len,
sim_fs_op_retrieve_cb, fs);
break;
default:
@@ -700,7 +723,7 @@
* It's an info-only request, so there is no need to request
* actual contents of the EF. Just return the EF-info.
*/
- sim_fs_read_info_cb_t cb = op->cb;
+ ofono_sim_read_info_cb_t cb = op->cb;
cb(1, file_status, op->length,
op->record_length, op->userdata);
@@ -778,7 +801,7 @@
* It's an info-only request, so there is no need to request
* actual contents of the EF. Just return the EF-info.
*/
- sim_fs_read_info_cb_t cb = op->cb;
+ ofono_sim_read_info_cb_t cb = op->cb;
cb(1, file_status, op->length,
op->record_length, op->userdata);
@@ -820,7 +843,28 @@
return FALSE;
}
- if (op->is_read == TRUE) {
+ if (op->is_read == TRUE && op->current > 0) {
+ switch (op->structure) {
+ case OFONO_SIM_FILE_STRUCTURE_FIXED:
+ driver->read_file_linear(fs->sim, op->id,
+ op->current, op->record_length,
+ op->path_len ? op->path : NULL,
+ op->path_len,
+ sim_fs_op_read_record_cb, fs);
+ break;
+ case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
+ driver->read_file_cyclic(fs->sim, op->id,
+ op->current, op->record_length,
+ op->path_len ? op->path : NULL,
+ op->path_len,
+ sim_fs_op_read_record_cb, fs);
+ break;
+ case OFONO_SIM_FILE_STRUCTURE_TRANSPARENT:
+ default:
+ ofono_error("Wrong file structure for reading record");
+ break;
+ }
+ } else if (op->is_read == TRUE) {
if (sim_fs_op_check_cached(fs))
return FALSE;
@@ -859,7 +903,8 @@
int sim_fs_read_info(struct ofono_sim_context *context, int id,
enum ofono_sim_file_structure expected_type,
- sim_fs_read_info_cb_t cb, void *data)
+ const unsigned char *path, unsigned int pth_len,
+ ofono_sim_read_info_cb_t cb, void *data)
{
struct sim_fs *fs = context->fs;
struct sim_fs_op *op;
@@ -887,6 +932,8 @@
op->is_read = TRUE;
op->info_only = TRUE;
op->context = context;
+ memcpy(op->path, path, pth_len);
+ op->path_len = pth_len;
g_queue_push_tail(fs->op_q, op);
@@ -935,6 +982,59 @@
memcpy(op->path, path, path_len);
op->path_len = path_len;
+ g_queue_push_tail(fs->op_q, op);
+
+ if (g_queue_get_length(fs->op_q) == 1)
+ fs->op_source = g_idle_add(sim_fs_op_next, fs);
+
+ return 0;
+}
+
+int sim_fs_read_record(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ int record, int record_length,
+ const unsigned char *path, unsigned int path_len,
+ ofono_sim_file_read_cb_t cb, void *data)
+{
+ struct sim_fs *fs = context->fs;
+ struct sim_fs_op *op;
+
+ if (cb == NULL)
+ return -EINVAL;
+
+ if (fs->driver == NULL)
+ return -EINVAL;
+
+ if (record < 1)
+ return -EINVAL;
+
+ if ((expected_type == OFONO_SIM_FILE_STRUCTURE_FIXED &&
+ fs->driver->read_file_linear == NULL) ||
+ (expected_type == OFONO_SIM_FILE_STRUCTURE_CYCLIC &&
+ fs->driver->read_file_cyclic == NULL)) {
+ cb(0, 0, 0, NULL, 0, data);
+ return -ENOSYS;
+ }
+
+ if (fs->op_q == NULL)
+ fs->op_q = g_queue_new();
+
+ op = g_try_new0(struct sim_fs_op, 1);
+ if (op == NULL)
+ return -ENOMEM;
+
+ op->id = id;
+ op->structure = expected_type;
+ op->cb = cb;
+ op->userdata = data;
+ op->is_read = TRUE;
+ op->info_only = FALSE;
+ op->context = context;
+ op->record_length = record_length;
+ op->current = record;
+ memcpy(op->path, path, path_len);
+ op->path_len = path_len;
+
g_queue_push_tail(fs->op_q, op);
if (g_queue_get_length(fs->op_q) == 1)
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.17+git19.tar.bz2/ofono/src/simfs.h
^
|
@@ -21,10 +21,6 @@
struct sim_fs;
-typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
- int total_length, int record_length,
- void *userdata);
-
struct sim_fs *sim_fs_new(struct ofono_sim *sim,
const struct ofono_sim_driver *driver);
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
@@ -45,9 +41,16 @@
const unsigned char *path, unsigned int len,
ofono_sim_file_read_cb_t cb, void *data);
+int sim_fs_read_record(struct ofono_sim_context *context, int id,
+ enum ofono_sim_file_structure expected_type,
+ int record, int record_length,
+ const unsigned char *path, unsigned int len,
+ ofono_sim_file_read_cb_t cb, void *data);
+
int sim_fs_read_info(struct ofono_sim_context *context, int id,
enum ofono_sim_file_structure expected_type,
- sim_fs_read_info_cb_t cb, void *data);
+ const unsigned char *path, unsigned int pth_len,
+ ofono_sim_read_info_cb_t cb, void *data);
void sim_fs_check_version(struct sim_fs *fs);
|