Merge sysmocom/lynxis/master into sysmocom/osmo-gsm-tester

Conflicts: plugins/gobi.c
This commit is contained in:
Alexander Couzens 2017-09-12 13:39:17 +02:00
commit 1056147002
49 changed files with 1466 additions and 88 deletions

View File

@ -123,3 +123,5 @@ Piotr Haber <gluedig@gmail.com>
André Draszik <git@andred.net>
Lukasz Nowak <lnowak@tycoint.com>
Jonas Bonn <jonas@southpole.se>
Matthijs Kooijman <matthijs@stdin.nl>
Clayton Craft <clayton@craftyguy.net>

View File

@ -236,7 +236,8 @@ builtin_sources += $(qmi_sources) \
drivers/qmimodem/gprs.c \
drivers/qmimodem/gprs-context.c \
drivers/qmimodem/radio-settings.c \
drivers/qmimodem/location-reporting.c
drivers/qmimodem/location-reporting.c \
drivers/qmimodem/qmibridge.c
builtin_modules += gobi
builtin_sources += plugins/gobi.c
@ -267,7 +268,8 @@ builtin_sources += drivers/atmodem/atmodem.h \
drivers/atmodem/gprs.c \
drivers/atmodem/gprs-context.c \
drivers/atmodem/sim-auth.c \
drivers/atmodem/gnss.c
drivers/atmodem/gnss.c \
drivers/atmodem/lte.c
builtin_modules += nwmodem
builtin_sources += drivers/atmodem/atutil.h \
@ -398,6 +400,11 @@ builtin_sources += drivers/atmodem/atutil.h \
drivers/gemaltomodem/gemaltomodem.c \
drivers/gemaltomodem/location-reporting.c
builtin_modules += xmm7modem
builtin_sources += drivers/atmodem/atutil.h \
drivers/xmm7modem/xmm7modem.h \
drivers/xmm7modem/xmm7modem.c \
drivers/xmm7modem/radio-settings.c
if PHONESIM
builtin_modules += phonesim
@ -623,10 +630,11 @@ src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \
src/cdma-provision.c src/handsfree.c \
src/handsfree-audio.c src/bluetooth.h \
src/hfp.h src/siri.c \
src/netmon.c src/lte.c src/call-list.c
src/netmon.c src/lte.c src/call-list.c \
src/netmonagent.c src/netmonagent.h
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
@GLIB_LIBS@ @DBUS_LIBS@ -ldl -lqmi-glib
src_ofonod_LDFLAGS = -Wl,--export-dynamic \
-Wl,--version-script=$(srcdir)/src/ofono.ver
@ -649,7 +657,7 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ $(builtin_cflags) \
AM_CPPFLAGS = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/src \
-I$(srcdir)/gdbus -I$(srcdir)/gisi -I$(srcdir)/gatchat \
-I$(srcdir)/btio -I$(srcdir)/gril
-I$(srcdir)/btio -I$(srcdir)/gril -I/usr/include/libqmi-glib
doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
doc/manager-api.txt doc/modem-api.txt doc/network-api.txt \
@ -776,7 +784,9 @@ test_scripts = test/backtrace \
test/list-allowed-access-points \
test/enable-throttling \
test/disable-throttling \
test/set-lte-property
test/set-lte-property \
test/test-serving-cell-info
if TEST
testdir = $(pkglibdir)/test

View File

@ -22,6 +22,34 @@ Methods a{sv} GetServingCellInformation()
are available, their valid value ranges and
applicability to different cell types.
void RegisterAgent(object path)
Registers an agent which will be called whenever the
modem registers to or moves to a new cell.
void UnregisterAgent(object path)
Unregisters an agent.
NetworkMonitorAgent Hierarchy [experimental]
=============================
Service unique name
Interface org.ofono.NetworkMonitorAgent
Object path freely definable
Methods void ServingCellInformationChanged(a{sv}) [noreply]
This method is called whenever the serving cell
information has been updated.
Possible Errors: None
void Release() [noreply]
Agent is being released, possibly because of oFono
terminating, NetworkMonitor interface is being torn
down or modem off. No UnregisterAgent call is needed.
Network Monitor Property Types
==============================
@ -77,7 +105,7 @@ byte TimingAdvance [optional, gsm]
Contains the Timing Advance. Valid range of values is 0-219.
byte Strength [optional, gsm, umts]
byte Strength [optional, gsm, umts, lte]
Contains the signal strength. Valid values are 0-31. Refer to <rssi>
in 27.007, Section 8.5.

View File

@ -52,6 +52,7 @@ static int atmodem_init(void)
at_gprs_context_init();
at_sim_auth_init();
at_gnss_init();
at_lte_init();
return 0;
}
@ -76,6 +77,7 @@ static void atmodem_exit(void)
at_gprs_exit();
at_gprs_context_exit();
at_gnss_exit();
at_lte_exit();
}
OFONO_PLUGIN_DEFINE(atmodem, "AT modem driver", VERSION,

View File

@ -74,3 +74,6 @@ extern void at_sim_auth_exit(void);
extern void at_gnss_init(void);
extern void at_gnss_exit(void);
extern void at_lte_init(void);
extern void at_lte_exit(void);

View File

@ -51,9 +51,7 @@ enum at_util_charset {
typedef void (*at_util_sim_inserted_cb_t)(gboolean present, void *userdata);
void decode_at_error(struct ofono_error *error, const char *final);
gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b);
gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
gint ofono_call_compare_by_id(gconstpointer a, gconstpointer b);
GSList *at_util_parse_clcc(GAtResult *result, unsigned int *mpty_ids);
gboolean at_util_parse_reg(GAtResult *result, const char *prefix,
int *mode, int *status,

View File

@ -43,7 +43,7 @@
#include "atmodem.h"
#include "vendor.h"
#define TUN_SYSFS_DIR "/sys/devices/virtual/misc/tun"
#define TUN_DEV "/dev/net/tun"
#define STATIC_IP_NETMASK "255.255.255.255"
@ -426,7 +426,7 @@ static int at_gprs_context_probe(struct ofono_gprs_context *gc,
DBG("");
if (stat(TUN_SYSFS_DIR, &st) < 0) {
if (stat(TUN_DEV, &st) < 0) {
ofono_error("Missing support for TUN/TAP devices");
return -ENODEV;
}

View File

@ -327,6 +327,26 @@ static void huawei_mode_notify(GAtResult *result, gpointer user_data)
ofono_gprs_bearer_notify(gprs, bearer);
}
static void huawei_hcsq_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
GAtResultIter iter;
const char *mode;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "^HCSQ:"))
return;
if (!g_at_result_iter_next_string(&iter, &mode))
return;
if (!strcmp("LTE", mode))
ofono_gprs_bearer_notify(gprs, 7); /* LTE */
/* in other modes, notification ^MODE is used */
}
static void telit_mode_notify(GAtResult *result, gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
@ -432,6 +452,8 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
case OFONO_VENDOR_HUAWEI:
g_at_chat_register(gd->chat, "^MODE:", huawei_mode_notify,
FALSE, gprs, NULL);
g_at_chat_register(gd->chat, "^HCSQ:", huawei_hcsq_notify,
FALSE, gprs, NULL);
break;
case OFONO_VENDOR_UBLOX:
case OFONO_VENDOR_UBLOX_TOBY_L2:

142
drivers/atmodem/lte.c Normal file
View File

@ -0,0 +1,142 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* 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.
*
* 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
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <ofono/modem.h>
#include <ofono/gprs-context.h>
#include <ofono/log.h>
#include <ofono/lte.h>
#include "gatchat.h"
#include "gatresult.h"
#include "atmodem.h"
struct lte_driver_data {
GAtChat *chat;
};
static void at_lte_set_default_attach_info_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_lte_cb_t cb = cbd->cb;
struct ofono_error error;
DBG("ok %d", ok);
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void at_lte_set_default_attach_info(const struct ofono_lte *lte,
const struct ofono_lte_default_attach_info *info,
ofono_lte_cb_t cb, void *data)
{
struct lte_driver_data *ldd = ofono_lte_get_data(lte);
char buf[32 + OFONO_GPRS_MAX_APN_LENGTH + 1];
struct cb_data *cbd = cb_data_new(cb, data);
DBG("LTE config with APN: %s", info->apn);
if (strlen(info->apn) > 0)
snprintf(buf, sizeof(buf), "AT+CGDCONT=0,\"IP\",\"%s\"",
info->apn);
else
snprintf(buf, sizeof(buf), "AT+CGDCONT=0,\"IP\"");
/* We can't do much in case of failure so don't check response. */
if (g_at_chat_send(ldd->chat, buf, NULL,
at_lte_set_default_attach_info_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, data);
}
static gboolean lte_delayed_register(gpointer user_data)
{
struct ofono_lte *lte = user_data;
ofono_lte_register(lte);
return FALSE;
}
static int at_lte_probe(struct ofono_lte *lte, void *data)
{
GAtChat *chat = data;
struct lte_driver_data *ldd;
DBG("at lte probe");
ldd = g_try_new0(struct lte_driver_data, 1);
if (!ldd)
return -ENOMEM;
ldd->chat = g_at_chat_clone(chat);
ofono_lte_set_data(lte, ldd);
g_idle_add(lte_delayed_register, lte);
return 0;
}
static void at_lte_remove(struct ofono_lte *lte)
{
struct lte_driver_data *ldd = ofono_lte_get_data(lte);
DBG("at lte remove");
g_at_chat_unref(ldd->chat);
ofono_lte_set_data(lte, NULL);
g_free(ldd);
}
static struct ofono_lte_driver driver = {
.name = "atmodem",
.probe = at_lte_probe,
.remove = at_lte_remove,
.set_default_attach_info = at_lte_set_default_attach_info,
};
void at_lte_init(void)
{
ofono_lte_driver_register(&driver);
}
void at_lte_exit(void)
{
ofono_lte_driver_unregister(&driver);
}

View File

@ -1088,6 +1088,27 @@ static void huawei_mode_notify(GAtResult *result, gpointer user_data)
}
}
static void huawei_hcsq_notify(GAtResult *result, gpointer user_data)
{
struct ofono_netreg *netreg = user_data;
struct netreg_data *nd = ofono_netreg_get_data(netreg);
GAtResultIter iter;
const char *mode;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "^HCSQ:"))
return;
if (!g_at_result_iter_next_string(&iter, &mode))
return;
if (!strcmp("LTE", mode))
nd->tech = ACCESS_TECHNOLOGY_EUTRAN;
/* for other technologies, notification ^MODE is used */
}
static void huawei_nwtime_notify(GAtResult *result, gpointer user_data)
{
struct ofono_netreg *netreg = user_data;
@ -1896,6 +1917,10 @@ static void at_creg_set_cb(gboolean ok, GAtResult *result, gpointer user_data)
g_at_chat_register(nd->chat, "^MODE:", huawei_mode_notify,
FALSE, netreg, NULL);
/* Register for 4G system mode reports */
g_at_chat_register(nd->chat, "^HCSQ:", huawei_hcsq_notify,
FALSE, netreg, NULL);
/* Register for network time reports */
g_at_chat_register(nd->chat, "^NWTIME:", huawei_nwtime_notify,
FALSE, netreg, NULL);

View File

@ -43,7 +43,7 @@
#include "cdmamodem.h"
#include "drivers/atmodem/vendor.h"
#define TUN_SYSFS_DIR "/sys/devices/virtual/misc/tun"
#define TUN_DEV "/dev/net/tun"
#define STATIC_IP_NETMASK "255.255.255.255"
@ -285,7 +285,7 @@ static int cdma_connman_probe(struct ofono_cdma_connman *cm,
DBG("");
if (stat(TUN_SYSFS_DIR, &st) < 0) {
if (stat(TUN_DEV, &st) < 0) {
ofono_error("Missing support for TUN/TAP devices");
return -ENODEV;
}

View File

@ -42,7 +42,7 @@
#include "ifxmodem.h"
#define TUN_SYSFS_DIR "/sys/devices/virtual/misc/tun"
#define TUN_DEV "/dev/net/tun"
#define STATIC_IP_NETMASK "255.255.255.255"
@ -470,7 +470,7 @@ static int ifx_gprs_context_probe(struct ofono_gprs_context *gc,
DBG("");
if (stat(TUN_SYSFS_DIR, &st) < 0) {
if (stat(TUN_DEV, &st) < 0) {
ofono_error("Missing support for TUN/TAP devices");
return -ENODEV;
}

View File

@ -646,8 +646,31 @@ error:
/* ISI callback: PIN state (enabled/disabled) query */
static void sec_code_state_resp_cb(const GIsiMessage *msg, void *opaque)
{
check_sec_response(msg, opaque, SEC_CODE_STATE_OK_RESP,
SEC_CODE_STATE_FAIL_RESP);
struct isi_cb_data *cbd = opaque;
ofono_query_facility_lock_cb_t cb = cbd->cb;
int locked;
uint8_t state;
uint8_t status;
if (!g_isi_msg_data_get_byte(msg, 0, &state) ||
!g_isi_msg_data_get_byte(msg, 1, &status))
goto error;
if (state != SEC_CODE_STATE_OK_RESP)
goto error;
if (status == SEC_CODE_ENABLE)
locked = 1;
else if (status == SEC_CODE_DISABLE)
locked = 0;
else
goto error;
CALLBACK_WITH_SUCCESS(cb, locked, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void isi_query_locked(struct ofono_sim *sim,

View File

@ -35,6 +35,8 @@
#define QMI_NAS_SS_INFO_IND 36 /* Current serving system info indication */
#define QMI_NAS_GET_HOME_INFO 37 /* Get info about home network */
#define QMI_NAS_SET_SYSTEM_SELECTION_PREF 51
#define QMI_NAS_GET_SYSTEM_SELECTION_PREF 52
/* Set NAS state report conditions */
#define QMI_NAS_PARAM_REPORT_SIGNAL_STRENGTH 0x10
@ -176,4 +178,13 @@ struct qmi_nas_home_network {
char desc[0];
} __attribute__((__packed__));
#define QMI_NAS_RAT_MODE_PREF_ANY (-1)
#define QMI_NAS_RAT_MODE_PREF_GSM (1 << 2)
#define QMI_NAS_RAT_MODE_PREF_UMTS (1 << 3)
#define QMI_NAS_RAT_MODE_PREF_LTE (1 << 4)
#define QMI_NAS_PARAM_SYSTEM_SELECTION_PREF_MODE 0x11
#define QMI_NAS_RESULT_SYSTEM_SELECTION_PREF_MODE 0x11
int qmi_nas_rat_to_tech(uint8_t rat);

View File

@ -48,14 +48,14 @@ static bool extract_ss_info_time(
struct qmi_result *result,
struct ofono_network_time *time)
{
const struct qmi_nas_3gpp_time *time_3gpp= NULL;
const struct qmi_nas_3gpp_time *time_3gpp = NULL;
uint8_t dst_3gpp;
bool dst_3gpp_valid;
uint16_t len;
/* parse 3gpp time & dst */
dst_3gpp_valid = qmi_result_get_uint8(result, QMI_NAS_RESULT_3GGP_DST,
&dst_3gpp);
&dst_3gpp);
time_3gpp = qmi_result_get(result, QMI_NAS_RESULT_3GPP_TIME, &len);
if (time_3gpp && len == sizeof(struct qmi_nas_3gpp_time) &&
@ -65,7 +65,7 @@ static bool extract_ss_info_time(
time->mday = time_3gpp->day;
time->hour = time_3gpp->hour;
time->min = time_3gpp->minute;
time->sec= time_3gpp->second;
time->sec = time_3gpp->second;
time->utcoff = time_3gpp->timezone * 15 * 60;
time->dst = dst_3gpp;
return true;
@ -487,10 +487,11 @@ static void event_notify(struct qmi_result *result, void *user_data)
if (ss) {
int strength;
DBG("signal with %d dBm on %d", ss->dbm, ss->rat);
strength = dbm_to_strength(ss->dbm);
DBG("signal with %d%%(%d dBm) on %d",
strength, ss->dbm, ss->rat);
ofono_netreg_strength_notify(netreg, strength);
}
@ -510,10 +511,17 @@ static void event_notify(struct qmi_result *result, void *user_data)
static void set_event_cb(struct qmi_result *result, void *user_data)
{
struct ofono_netreg *netreg = user_data;
struct netreg_data *data = ofono_netreg_get_data(netreg);
DBG("");
ofono_netreg_register(netreg);
qmi_service_register(data->nas, QMI_NAS_EVENT,
event_notify, netreg, NULL);
qmi_service_register(data->nas, QMI_NAS_SS_INFO_IND,
ss_info_notify, netreg, NULL);
}
static void create_nas_cb(struct qmi_service *service, void *user_data)
@ -535,12 +543,6 @@ static void create_nas_cb(struct qmi_service *service, void *user_data)
data->nas = qmi_service_ref(service);
qmi_service_register(data->nas, QMI_NAS_EVENT,
event_notify, netreg, NULL);
qmi_service_register(data->nas, QMI_NAS_SS_INFO_IND,
ss_info_notify, netreg, NULL);
param = qmi_param_new();
if (!param)
goto done;

View File

@ -37,6 +37,7 @@
#include <ofono/log.h>
#include "qmibridge.h"
#include "qmi.h"
#include "ctl.h"
@ -651,6 +652,8 @@ static gboolean can_write_data(GIOChannel *channel, GIOCondition cond,
__debug_msg(' ', req->buf, bytes_written,
device->debug_func, device->debug_data);
qmibridge_decode_req(req->buf, req->len);
hdr = req->buf;
if (hdr->service == QMI_SERVICE_CONTROL)
@ -838,6 +841,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond,
__hexdump('<', buf, bytes_read,
device->debug_func, device->debug_data);
qmibridge_decode_read(buf, bytes_read);
offset = 0;
while (offset < bytes_read) {
@ -1136,15 +1140,12 @@ static void discover_callback(uint16_t message, uint16_t length,
if (type == QMI_SERVICE_CONTROL) {
device->control_major = major;
device->control_minor = minor;
continue;
}
list[count].type = type;
list[count].major = major;
list[count].minor = minor;
list[count].name = name;
count++;
list[i].type = type;
list[i].major = major;
list[i].minor = minor;
list[i].name = name;
if (name)
__debug_device(device, "found service [%s %d.%d]",
@ -1153,6 +1154,7 @@ static void discover_callback(uint16_t message, uint16_t length,
__debug_device(device, "found service [%d %d.%d]",
type, major, minor);
}
count = service_list->count;
ptr = tlv_get(buffer, length, 0x10, &len);
if (!ptr)
@ -1162,11 +1164,6 @@ static void discover_callback(uint16_t message, uint16_t length,
service_list = ptr + *((uint8_t *) ptr) + 1;
for (i = 0; i < service_list->count; i++) {
if (service_list->services[i].type == QMI_SERVICE_CONTROL)
continue;
}
done:
device->version_list = list;
device->version_count = count;
@ -1767,6 +1764,27 @@ bool qmi_result_get_uint8(struct qmi_result *result, uint8_t type,
return true;
}
bool qmi_result_get_int16(struct qmi_result *result, uint8_t type,
int16_t *value)
{
const unsigned char *ptr;
uint16_t len, tmp;
if (!result || !type)
return false;
ptr = tlv_get(result->data, result->length, type, &len);
if (!ptr)
return false;
memcpy(&tmp, ptr, 2);
if (value)
*value = GINT16_FROM_LE(tmp);
return true;
}
bool qmi_result_get_uint16(struct qmi_result *result, uint8_t type,
uint16_t *value)
{

View File

@ -136,6 +136,8 @@ const void *qmi_result_get(struct qmi_result *result, uint8_t type,
char *qmi_result_get_string(struct qmi_result *result, uint8_t type);
bool qmi_result_get_uint8(struct qmi_result *result, uint8_t type,
uint8_t *value);
bool qmi_result_get_int16(struct qmi_result *result, uint8_t type,
int16_t *value);
bool qmi_result_get_uint16(struct qmi_result *result, uint8_t type,
uint16_t *value);
bool qmi_result_get_uint32(struct qmi_result *result, uint8_t type,

View File

@ -0,0 +1,40 @@
#include <libqmi-glib.h>
#include <string.h>
#include <stdio.h>
#include <ofono/log.h>
#include <glib.h>
static void ask_qmi(const char *prefix, void *data, size_t len)
{
/* from osmo-qcdiag */
GByteArray *buffer;
GError *error = NULL;
QmiMessage *message;
gchar *printable;
buffer = g_byte_array_sized_new(len);
g_byte_array_append(buffer, data, len);
message = qmi_message_new_from_raw(buffer, &error);
if (!message) {
fprintf(stderr, "qmi_message_new_from_raw() returned NULL\n");
return;
}
printable = qmi_message_get_printable(message, "QMI ");
DBG("%s: %s", prefix, printable);
g_free(printable);
}
void qmibridge_decode_read(void *data, size_t len)
{
ask_qmi("READ", data, len);
}
void qmibridge_decode_req(void *data, size_t len)
{
ask_qmi("_REQ", data, len);
}

View File

@ -0,0 +1,3 @@
void qmibridge_decode_read(void *data, size_t len);
void qmibridge_decode_req(void *data, size_t len);

View File

@ -29,15 +29,202 @@
#include "qmi.h"
#include "nas.h"
#include "dms.h"
#include "qmimodem.h"
struct settings_data {
struct qmi_service *nas;
struct qmi_service *dms;
uint16_t major;
uint16_t minor;
};
static void get_system_selection_pref_cb(struct qmi_result *result,
void* user_data)
{
struct cb_data *cbd = user_data;
ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
enum ofono_radio_access_mode mode = OFONO_RADIO_ACCESS_MODE_ANY;
uint16_t pref;
DBG("");
if (qmi_result_set_error(result, NULL)) {
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
return;
}
qmi_result_get_uint16(result,
QMI_NAS_RESULT_SYSTEM_SELECTION_PREF_MODE, &pref);
switch (pref) {
case QMI_NAS_RAT_MODE_PREF_GSM:
mode = OFONO_RADIO_ACCESS_MODE_GSM;
break;
case QMI_NAS_RAT_MODE_PREF_UMTS:
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
break;
case QMI_NAS_RAT_MODE_PREF_LTE:
mode = OFONO_RADIO_ACCESS_MODE_LTE;
break;
}
CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
}
static void qmi_query_rat_mode(struct ofono_radio_settings *rs,
ofono_radio_settings_rat_mode_query_cb_t cb,
void *user_data)
{
struct settings_data *data = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, user_data);
DBG("");
if (qmi_service_send(data->nas,
QMI_NAS_GET_SYSTEM_SELECTION_PREF, NULL,
get_system_selection_pref_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void set_system_selection_pref_cb(struct qmi_result *result,
void* user_data)
{
struct cb_data *cbd = user_data;
ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
DBG("");
if (qmi_result_set_error(result, NULL)) {
CALLBACK_WITH_FAILURE(cb, cbd->data);
return;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void qmi_set_rat_mode(struct ofono_radio_settings *rs,
enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_set_cb_t cb,
void *user_data)
{
struct settings_data *data = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, user_data);
uint16_t pref = QMI_NAS_RAT_MODE_PREF_ANY;
struct qmi_param *param;
DBG("");
switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
pref = QMI_NAS_RAT_MODE_PREF_ANY;
break;
case OFONO_RADIO_ACCESS_MODE_GSM:
pref = QMI_NAS_RAT_MODE_PREF_GSM;
break;
case OFONO_RADIO_ACCESS_MODE_UMTS:
pref = QMI_NAS_RAT_MODE_PREF_UMTS;
break;
case OFONO_RADIO_ACCESS_MODE_LTE:
pref = QMI_NAS_RAT_MODE_PREF_LTE;
break;
}
param = qmi_param_new();
if (!param) {
CALLBACK_WITH_FAILURE(cb, user_data);
return;
}
qmi_param_append_uint16(param, QMI_NAS_PARAM_SYSTEM_SELECTION_PREF_MODE,
pref);
if (qmi_service_send(data->nas,
QMI_NAS_SET_SYSTEM_SELECTION_PREF, param,
set_system_selection_pref_cb, cbd, g_free) > 0)
return;
qmi_param_free(param);
CALLBACK_WITH_FAILURE(cb, user_data);
g_free(cbd);
}
static void get_caps_cb(struct qmi_result *result, void *user_data)
{
struct cb_data *cbd = user_data;
ofono_radio_settings_available_rats_query_cb_t cb = cbd->cb;
const struct qmi_dms_device_caps *caps;
unsigned int available_rats;
uint16_t len;
uint8_t i;
DBG("");
if (qmi_result_set_error(result, NULL))
goto error;
caps = qmi_result_get(result, QMI_DMS_RESULT_DEVICE_CAPS, &len);
if (!caps)
goto error;
available_rats = 0;
for (i = 0; i < caps->radio_if_count; i++) {
switch (caps->radio_if[i]) {
case QMI_DMS_RADIO_IF_GSM:
available_rats |= OFONO_RADIO_ACCESS_MODE_GSM;
break;
case QMI_DMS_RADIO_IF_UMTS:
available_rats |= OFONO_RADIO_ACCESS_MODE_UMTS;
break;
case QMI_DMS_RADIO_IF_LTE:
available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
break;
}
}
CALLBACK_WITH_SUCCESS(cb, available_rats, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void qmi_query_available_rats(struct ofono_radio_settings *rs,
ofono_radio_settings_available_rats_query_cb_t cb,
void *data)
{
struct settings_data *rsd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data);
if (!rsd->dms)
goto error;
if (qmi_service_send(rsd->dms, QMI_DMS_GET_CAPS, NULL,
get_caps_cb, cbd, g_free) > 0)
return;
error:
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, -1, data);
}
static void create_dms_cb(struct qmi_service *service, void *user_data)
{
struct ofono_radio_settings *rs = user_data;
struct settings_data *data = ofono_radio_settings_get_data(rs);
DBG("");
if (!service)
return;
data->dms = qmi_service_ref(service);
}
static void create_nas_cb(struct qmi_service *service, void *user_data)
{
struct ofono_radio_settings *rs = user_data;
@ -74,11 +261,12 @@ static int qmi_radio_settings_probe(struct ofono_radio_settings *rs,
ofono_radio_settings_set_data(rs, data);
qmi_service_create_shared(device, QMI_SERVICE_DMS,
create_dms_cb, rs, NULL);
qmi_service_create_shared(device, QMI_SERVICE_NAS,
create_nas_cb, rs, NULL);
return 0;
}
static void qmi_radio_settings_remove(struct ofono_radio_settings *rs)
@ -100,6 +288,9 @@ static struct ofono_radio_settings_driver driver = {
.name = "qmimodem",
.probe = qmi_radio_settings_probe,
.remove = qmi_radio_settings_remove,
.set_rat_mode = qmi_set_rat_mode,
.query_rat_mode = qmi_query_rat_mode,
.query_available_rats = qmi_query_available_rats,
};
void qmi_radio_settings_init(void)

View File

@ -277,7 +277,7 @@ static void qmi_bearer_query(struct ofono_sms *sms,
DBG("");
if (data->major < 1 && data->minor < 2)
if (data->major < 1 || (data->major == 1 && data->minor < 2))
goto error;
if (qmi_service_send(data->wms, QMI_WMS_GET_DOMAIN_PREF, NULL,
@ -315,7 +315,7 @@ static void qmi_bearer_set(struct ofono_sms *sms, int bearer,
DBG("bearer %d", bearer);
if (data->major < 1 && data->minor < 2)
if (data->major < 1 || (data->major == 1 && data->minor < 2))
goto error;
domain = bearer_to_domain(bearer);

View File

@ -65,6 +65,9 @@ static void all_call_status_ind(struct qmi_result *result, void *user_data)
int i;
int size = 0;
struct qmi_voice_all_call_status_ind status_ind;
GSList *n, *o;
struct ofono_call *nc, *oc;
if (qmi_voice_ind_call_status(result, &status_ind) != NONE) {
DBG("Parsing of all call status indication failed");
@ -112,7 +115,7 @@ static void all_call_status_ind(struct qmi_result *result, void *user_data)
call->type = 0; /* always voice */
number_size = remote_party->number_size;
if (number_size > OFONO_MAX_PHONE_NUMBER_LENGTH)
number_size = OFONO_MAX_PHONE_NUMBER_LENGTH;
OFONO_MAX_PHONE_NUMBER_LENGTH;
strncpy(call->phone_number.number, remote_party->number,
number_size);
/* FIXME: set phone_number_type */
@ -201,6 +204,7 @@ static void dial_cb(struct qmi_result *result, void *user_data)
ofono_voicecall_cb_t cb = cbd->cb;
uint16_t error;
struct qmi_voice_dial_call_result dial_result;
struct ofono_call *call;
if (qmi_result_set_error(result, &error)) {
DBG("QMI Error %d", error);
@ -262,9 +266,11 @@ static void dial(struct ofono_voicecall *vc, const struct ofono_phone_number *ph
static void answer_cb(struct qmi_result *result, void *user_data)
{
struct cb_data *cbd = user_data;
struct ofono_voicecall *vc = cbd->user;
ofono_voicecall_cb_t cb = cbd->cb;
uint16_t error;
struct qmi_voice_answer_call_result answer_result;
struct ofono_call *call;
if (qmi_result_set_error(result, &error)) {
DBG("QMI Error %d", error);
@ -322,9 +328,11 @@ err:
static void end_cb(struct qmi_result *result, void *user_data)
{
struct cb_data *cbd = user_data;
struct ofono_voicecall *vc = cbd->user;
ofono_voicecall_cb_t cb = cbd->cb;
uint16_t error;
struct qmi_voice_end_call_result end_result;
struct ofono_call *call;
if (qmi_result_set_error(result, &error)) {
DBG("QMI Error %d", error);
@ -347,6 +355,7 @@ static void release_specific(struct ofono_voicecall *vc, int id,
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
struct cb_data *cbd = cb_data_new(cb, data);
struct qmi_voice_end_call_arg arg;
int i;
DBG("");
cbd->user = vc;
@ -369,19 +378,21 @@ static void hangup_active(struct ofono_voicecall *vc,
ofono_voicecall_cb_t cb, void *data)
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
struct qmi_voice_end_call_arg arg;
struct ofono_call *call;
GSList *list = NULL;
enum call_status active[] = {
CALL_STATUS_ACTIVE,
CALL_STATUS_DIALING,
CALL_STATUS_ALERTING
CALL_STATUS_ALERTING,
CALL_STATUS_INCOMING,
};
int i;
DBG("");
for (i = 0; i < ARRAY_SIZE(active); i++) {
list = g_slist_find_custom(vd->call_list,
GINT_TO_POINTER(CALL_STATUS_ACTIVE),
GINT_TO_POINTER(active[i]),
ofono_call_compare_by_status);
if (list)

View File

@ -61,6 +61,9 @@
/* size of RIL_CellInfoTdscdma */
#define NETMON_RIL_CELLINFO_SIZE_TDSCDMA 24
#define MSECS_RATE_INVALID (0x7fffffff)
#define SECS_TO_MSECS(x) ((x) * 1000)
struct netmon_data {
GRil *ril;
};
@ -96,11 +99,9 @@ static int ril_cell_type_to_size(int cell_type)
return 0;
}
static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
static int process_cellinfo_list(struct ril_msg *message,
struct ofono_netmon *netmon)
{
struct cb_data *cbd = user_data;
ofono_netmon_cb_t cb = cbd->cb;
struct ofono_netmon *netmon = cbd->data;
struct parcel rilp;
int skip_len;
int cell_info_cnt;
@ -114,7 +115,7 @@ static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
int i, j;
if (message->error != RIL_E_SUCCESS)
goto error;
return OFONO_ERROR_TYPE_FAILURE;
g_ril_init_parcel(message, &rilp);
@ -146,7 +147,7 @@ static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
}
if (!registered)
goto error;
return OFONO_ERROR_TYPE_FAILURE;
if (cell_type == NETMON_RIL_CELLINFO_TYPE_GSM) {
mcc = parcel_r_int32(&rilp);
@ -216,17 +217,53 @@ static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
OFONO_NETMON_INFO_BER, ber,
OFONO_NETMON_INFO_INVALID);
} else {
goto error;
}
CALLBACK_WITH_SUCCESS(cb, cbd->data);
return;
return OFONO_ERROR_TYPE_NO_ERROR;
}
static void ril_netmon_update_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_netmon_cb_t cb = cbd->cb;
struct ofono_netmon *netmon = cbd->data;
if (process_cellinfo_list(message, netmon) ==
OFONO_ERROR_TYPE_NO_ERROR) {
CALLBACK_WITH_SUCCESS(cb, cbd->data);
return;
}
error:
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static void ril_cellinfo_notify(struct ril_msg *message, gpointer user_data)
{
struct ofono_netmon *netmon = user_data;
process_cellinfo_list(message, netmon);
}
static void setup_cell_info_notify(struct ofono_netmon *netmon)
{
struct netmon_data *nmd = ofono_netmon_get_data(netmon);
struct parcel rilp;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of elements */
parcel_w_int32(&rilp, MSECS_RATE_INVALID);
if (g_ril_send(nmd->ril, RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE,
&rilp, NULL, NULL, NULL) == 0)
ofono_error("%s: setup failed\n", __func__);
if (g_ril_register(nmd->ril, RIL_UNSOL_CELL_INFO_LIST,
ril_cellinfo_notify, netmon) == 0)
ofono_error("%s: setup failed\n", __func__);
}
static int ril_netmon_probe(struct ofono_netmon *netmon,
unsigned int vendor, void *user)
{
@ -237,6 +274,8 @@ static int ril_netmon_probe(struct ofono_netmon *netmon,
ofono_netmon_set_data(netmon, ud);
setup_cell_info_notify(netmon);
g_idle_add(ril_delayed_register, netmon);
return 0;
@ -257,18 +296,55 @@ static void ril_netmon_request_update(struct ofono_netmon *netmon,
struct cb_data *cbd = cb_data_new(cb, data, nmd);
if (g_ril_send(nmd->ril, RIL_REQUEST_GET_CELL_INFO_LIST, NULL,
ril_netmon_update_cb, cbd, NULL) > 0)
ril_netmon_update_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void periodic_update_cb(struct ril_msg *message, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_netmon_cb_t cb = cbd->cb;
if (message->error != RIL_E_SUCCESS)
CALLBACK_WITH_FAILURE(cb, cbd->data);
CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void ril_netmon_periodic_update(struct ofono_netmon *netmon,
unsigned int enable, unsigned int period,
ofono_netmon_cb_t cb, void *data)
{
struct netmon_data *nmd = ofono_netmon_get_data(netmon);
struct cb_data *cbd = cb_data_new(cb, data, nmd);
struct parcel rilp;
parcel_init(&rilp);
parcel_w_int32(&rilp, 1); /* Number of elements */
if (enable)
parcel_w_int32(&rilp, SECS_TO_MSECS(period));
else
parcel_w_int32(&rilp, MSECS_RATE_INVALID);
if (g_ril_send(nmd->ril, RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE,
&rilp, periodic_update_cb, cbd, g_free) > 0)
return;
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, cbd->data);
}
static struct ofono_netmon_driver driver = {
.name = RILMODEM,
.probe = ril_netmon_probe,
.remove = ril_netmon_remove,
.request_update = ril_netmon_request_update,
.enable_periodic_update = ril_netmon_periodic_update,
};
void ril_netmon_init(void)

View File

@ -0,0 +1,233 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* 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.
*
* 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
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <glib.h>
#include <ofono/log.h>
#include <ofono/modem.h>
#include <ofono/radio-settings.h>
#include "gatchat.h"
#include "gatresult.h"
#include "xmm7modem.h"
static const char *none_prefix[] = { NULL };
static const char *xact_prefix[] = { "+XACT:", NULL };
struct radio_settings_data {
GAtChat *chat;
};
static void xact_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
enum ofono_radio_access_mode mode;
struct ofono_error error;
GAtResultIter iter;
int value, preferred;
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, -1, cbd->data);
return;
}
g_at_result_iter_init(&iter, result);
if (g_at_result_iter_next(&iter, "+XACT:") == FALSE)
goto error;
if (g_at_result_iter_next_number(&iter, &value) == FALSE)
goto error;
if (g_at_result_iter_next_number(&iter, &preferred) == FALSE)
goto error;
switch (value) {
case 0:
mode = OFONO_RADIO_ACCESS_MODE_GSM;
break;
case 1:
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
break;
case 2:
mode = OFONO_RADIO_ACCESS_MODE_LTE;
break;
case 3:
mode = OFONO_RADIO_ACCESS_MODE_UMTS;
break;
case 4:
mode = OFONO_RADIO_ACCESS_MODE_LTE;
break;
case 5:
mode = OFONO_RADIO_ACCESS_MODE_LTE;
break;
case 6:
mode = OFONO_RADIO_ACCESS_MODE_ANY;
break;
default:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
return;
}
cb(&error, mode, cbd->data);
return;
error:
CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
}
static void xmm_query_rat_mode(struct ofono_radio_settings *rs,
ofono_radio_settings_rat_mode_query_cb_t cb,
void *data)
{
struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data);
if (g_at_chat_send(rsd->chat, "AT+XACT?", xact_prefix,
xact_query_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, -1, data);
g_free(cbd);
}
static void xact_modify_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
struct ofono_error error;
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void xmm_set_rat_mode(struct ofono_radio_settings *rs,
enum ofono_radio_access_mode mode,
ofono_radio_settings_rat_mode_set_cb_t cb,
void *data)
{
struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
struct cb_data *cbd = cb_data_new(cb, data);
char buf[20];
int value = 6, preferred = 2;
switch (mode) {
case OFONO_RADIO_ACCESS_MODE_ANY:
value = 6;
break;
case OFONO_RADIO_ACCESS_MODE_GSM:
value = 0;
break;
case OFONO_RADIO_ACCESS_MODE_UMTS:
value = 1;
break;
case OFONO_RADIO_ACCESS_MODE_LTE:
value = 2;
break;
}
if (value == 6)
snprintf(buf, sizeof(buf), "AT+XACT=%u,%u", value, preferred);
else
snprintf(buf, sizeof(buf), "AT+XACT=%u", value);
if (g_at_chat_send(rsd->chat, buf, none_prefix,
xact_modify_cb, cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, data);
g_free(cbd);
}
static void xact_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_radio_settings *rs = user_data;
if (!ok) {
ofono_radio_settings_remove(rs);
return;
}
ofono_radio_settings_register(rs);
}
static int xmm_radio_settings_probe(struct ofono_radio_settings *rs,
unsigned int vendor, void *user)
{
GAtChat *chat = user;
struct radio_settings_data *rsd;
rsd = g_try_new0(struct radio_settings_data, 1);
if (rsd == NULL)
return -ENOMEM;
rsd->chat = g_at_chat_clone(chat);
ofono_radio_settings_set_data(rs, rsd);
g_at_chat_send(rsd->chat, "AT+XACT=?", xact_prefix,
xact_support_cb, rs, NULL);
return 0;
}
static void xmm_radio_settings_remove(struct ofono_radio_settings *rs)
{
struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
ofono_radio_settings_set_data(rs, NULL);
g_at_chat_unref(rsd->chat);
g_free(rsd);
}
static struct ofono_radio_settings_driver driver = {
.name = "xmm7modem",
.probe = xmm_radio_settings_probe,
.remove = xmm_radio_settings_remove,
.query_rat_mode = xmm_query_rat_mode,
.set_rat_mode = xmm_set_rat_mode
};
void xmm_radio_settings_init(void)
{
ofono_radio_settings_driver_register(&driver);
}
void xmm_radio_settings_exit(void)
{
ofono_radio_settings_driver_unregister(&driver);
}

View File

@ -0,0 +1,50 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* 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.
*
* 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
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <gatchat.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
#include <ofono/types.h>
#include <ofono/modem.h>
#include "xmm7modem.h"
static int xmm7modem_init(void)
{
xmm_radio_settings_init();
return 0;
}
static void xmm7modem_exit(void)
{
xmm_radio_settings_exit();
}
OFONO_PLUGIN_DEFINE(xmm7modem, "Intel xmm7xxx series modem driver",
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
xmm7modem_init, xmm7modem_exit)

View File

@ -0,0 +1,27 @@
/*
*
* oFono - Open Source Telephony
*
* Copyright (C) 2017 Intel Corporation. All rights reserved.
*
* 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.
*
* 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 <drivers/atmodem/atutil.h>
#define XMM7MODEM "xmm7modem"
extern void xmm_radio_settings_init(void);
extern void xmm_radio_settings_exit(void);

View File

@ -338,6 +338,8 @@ const char *ril_request_id_to_string(int req)
return "RIL_REQUEST_GET_CELL_INFO_LIST";
case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
return "RIL_REQUEST_SET_INITIAL_ATTACH_APN";
case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
return "RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE";
default:
return "<INVALID>";
}
@ -416,6 +418,8 @@ const char *ril_unsol_request_to_string(int request)
return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
case RIL_UNSOL_RIL_CONNECTED:
return "UNSOL_RIL_CONNECTED";
case RIL_UNSOL_CELL_INFO_LIST:
return "RIL_UNSOL_CELL_INFO_LIST";
default:
return "<unknown request>";
}

View File

@ -23,6 +23,7 @@
#define __PARCEL_H
#include <stdlib.h>
#include <stdint.h>
struct parcel {
char *data;

View File

@ -348,6 +348,7 @@
#define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107
#define RIL_REQUEST_VOICE_RADIO_TECH 108
#define RIL_REQUEST_GET_CELL_INFO_LIST 109
#define RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE 110
#define RIL_REQUEST_SET_INITIAL_ATTACH_APN 111
/* RIL Unsolicited Messages */
@ -388,6 +389,7 @@
#define RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE 1033
#define RIL_UNSOL_RIL_CONNECTED 1034
#define RIL_UNSOL_VOICE_RADIO_TECH_CHANGED 1035
#define RIL_UNSOL_CELL_INFO_LIST 1036
/* Suplementary services Service class*/
#define SERVICE_CLASS_NONE 0

View File

@ -61,6 +61,7 @@ extern "C" {
#define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
#define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
#define OFONO_NETMON_INTERFACE OFONO_SERVICE ".NetworkMonitor"
#define OFONO_NETMON_AGENT_INTERFACE OFONO_SERVICE ".NetworkMonitorAgent"
#define OFONO_LTE_INTERFACE OFONO_SERVICE ".LongTermEvolution"
/* CDMA Interfaces */

View File

@ -29,7 +29,13 @@ extern "C" {
#include <ofono/types.h>
struct ofono_gprs_context;
struct ofono_modem;
/*
* ETSI 123.003, Section 9.1:
* the APN has, after encoding as defined in the paragraph below, a maximum
* length of 100 octets
*/
#define OFONO_GPRS_MAX_APN_LENGTH 100
#define OFONO_GPRS_MAX_USERNAME_LENGTH 63
#define OFONO_GPRS_MAX_PASSWORD_LENGTH 255

View File

@ -39,6 +39,10 @@ struct ofono_netmon_driver {
void (*remove)(struct ofono_netmon *netmon);
void (*request_update)(struct ofono_netmon *netmon,
ofono_netmon_cb_t cb, void *data);
void (*enable_periodic_update)(struct ofono_netmon *netmon,
unsigned int enable,
unsigned int period,
ofono_netmon_cb_t cb, void *data);
};
enum ofono_netmon_cell_type {

View File

@ -25,6 +25,7 @@
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <glib.h>
#include <gatchat.h>

View File

@ -252,6 +252,15 @@ error:
shutdown_device(modem);
}
static void create_shared_dms(void *user_data)
{
struct ofono_modem *modem = user_data;
struct gobi_data *data = ofono_modem_get_data(modem);
qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
create_dms_cb, modem, NULL);
}
static void discover_cb(uint8_t count, const struct qmi_version *list,
void *user_data)
{
@ -266,6 +275,13 @@ static void discover_cb(uint8_t count, const struct qmi_version *list,
list[i].type);
switch (list[i].type) {
case QMI_SERVICE_CONTROL:
/* sync command resets the QMI state */
if (list[i].major > 1 || list[i].minor >= 5)
ofono_modem_set_boolean(modem,
"SupportQMISync",
TRUE);
break;
case QMI_SERVICE_DMS:
data->features |= GOBI_DMS;
break;
@ -314,18 +330,10 @@ static void discover_cb(uint8_t count, const struct qmi_version *list,
return;
}
qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
create_dms_cb, modem, NULL);
}
static void sync_cb(void *user_data)
{
struct ofono_modem *modem = user_data;
struct gobi_data *data = ofono_modem_get_data(modem);
DBG("modem in sync");
qmi_device_discover(data->device, discover_cb, modem, NULL);
if (ofono_modem_get_boolean(modem, "SupportQMISync") == TRUE)
qmi_device_sync(data->device, create_shared_dms, modem);
else
create_shared_dms(modem);
}
static int gobi_enable(struct ofono_modem *modem)
@ -355,7 +363,7 @@ static int gobi_enable(struct ofono_modem *modem)
qmi_device_set_close_on_unref(data->device, true);
qmi_device_sync(data->device, sync_cb, modem);
qmi_device_discover(data->device, discover_cb, modem, NULL);
return -EINPROGRESS;
}

View File

@ -261,18 +261,34 @@ static gboolean setup_sierra(struct modem_info *modem)
if (g_strcmp0(info->interface, "255/255/255") == 0) {
if (g_strcmp0(info->number, "01") == 0)
diag = info->devnode;
if (g_strcmp0(info->number, "03") == 0)
else if (g_strcmp0(info->number, "03") == 0)
mdm = info->devnode;
else if (g_strcmp0(info->number, "04") == 0)
app = info->devnode;
else if (g_strcmp0(info->number, "07") == 0)
net = info->devnode;
else if (g_strcmp0(info->number, "0a") == 0) {
if (g_strcmp0(info->subsystem, "net") == 0)
else if (g_strcmp0(info->subsystem, "net") == 0) {
/*
* When using the voice firmware on a mc7304
* the second cdc-wdm interface doesn't handle
* qmi messages properly.
* Some modems still have a working second
* cdc-wdm interface, some are not. But always
* the first interface works.
*/
if (g_strcmp0(info->number, "08") == 0) {
net = info->devnode;
else if (g_strcmp0(info->subsystem,
"usbmisc") == 0)
} else if (g_strcmp0(info->number, "0a") == 0) {
if (net == NULL)
net = info->devnode;
}
} else if (g_strcmp0(info->subsystem, "usbmisc") == 0) {
if (g_strcmp0(info->number, "08") == 0) {
qmi = info->devnode;
} else if (g_strcmp0(info->number, "0a") == 0) {
if (qmi == NULL)
qmi = info->devnode;
}
}
}
}
@ -860,7 +876,7 @@ static gboolean setup_quectel(struct modem_info *modem)
static gboolean setup_quectelqmi(struct modem_info *modem)
{
const char *qmi = NULL, *net = NULL, *gps = NULL;
const char *qmi = NULL, *net = NULL, *gps = NULL, *aux = NULL;
GSList *list;
DBG("%s", modem->syspath);
@ -878,8 +894,11 @@ static gboolean setup_quectelqmi(struct modem_info *modem)
else if (g_strcmp0(info->subsystem, "usbmisc") == 0)
qmi = info->devnode;
} else if (g_strcmp0(info->interface, "255/0/0") == 0 &&
g_strcmp0(info->number, "02") == 0) {
g_strcmp0(info->number, "01") == 0) {
gps = info->devnode;
} else if (g_strcmp0(info->interface, "255/0/0") == 0 &&
g_strcmp0(info->number, "02") == 0) {
aux = info->devnode;
}
}
@ -893,8 +912,12 @@ static gboolean setup_quectelqmi(struct modem_info *modem)
ofono_modem_set_string(modem->modem, "Device", qmi);
ofono_modem_set_string(modem->modem, "NetworkInterface", net);
DBG("gps=%s aux=%s", gps, aux);
if (gps)
ofono_modem_set_string(modem->modem, "GPS", gps);
if (aux)
ofono_modem_set_string(modem->modem, "Aux", aux);
ofono_modem_set_driver(modem->modem, "gobi");

View File

@ -704,6 +704,9 @@ gboolean is_valid_apn(const char *apn)
int i;
int last_period = 0;
if (apn == NULL)
return FALSE;
if (apn[0] == '.' || apn[0] == '\0')
return FALSE;
@ -742,6 +745,28 @@ void ofono_call_init(struct ofono_call *call)
call->clip_validity = CLIP_VALIDITY_NOT_AVAILABLE;
}
const char *call_status_to_string(enum call_status status)
{
switch (status) {
case CALL_STATUS_ACTIVE:
return "active";
case CALL_STATUS_HELD:
return "held";
case CALL_STATUS_DIALING:
return "dialing";
case CALL_STATUS_ALERTING:
return "alerting";
case CALL_STATUS_INCOMING:
return "incoming";
case CALL_STATUS_WAITING:
return "waiting";
case CALL_STATUS_DISCONNECTED:
return "disconnected";
}
return "unknown";
}
gint ofono_call_compare(gconstpointer a, gconstpointer b)
{
const struct ofono_call *ca = a;

View File

@ -184,6 +184,7 @@ const char *registration_tech_to_string(int tech);
const char *packet_bearer_to_string(int bearer);
gboolean is_valid_apn(const char *apn);
const char *call_status_to_string(enum call_status status);
gint ofono_call_compare(gconstpointer a, gconstpointer b);
gint ofono_call_compare_by_status(gconstpointer a, gconstpointer b);

View File

@ -2596,10 +2596,14 @@ void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status)
{
DBG("%s status %d", __ofono_atom_get_path(gprs->atom), status);
DBG("%s status %s (%d)", __ofono_atom_get_path(gprs->atom),
registration_status_to_string(status), status);
gprs->status = status;
if (status == 0)
ofono_gprs_detached_notify(gprs);
if (status != NETWORK_REGISTRATION_STATUS_REGISTERED &&
status != NETWORK_REGISTRATION_STATUS_ROAMING) {
gprs_attached_update(gprs);

View File

@ -34,6 +34,7 @@
#include <gdbus.h>
#include "ofono.h"
#include "netmonagent.h"
#define CELL_INFO_DICT_APPEND(p_dict, key, info, type, dbus_type) do { \
type value; \
@ -51,6 +52,7 @@ struct ofono_netmon {
DBusMessage *reply;
void *driver_data;
struct ofono_atom *atom;
struct netmon_agent *agent;
};
static const char *cell_type_to_tech_name(enum ofono_netmon_cell_type type)
@ -72,6 +74,7 @@ void ofono_netmon_serving_cell_notify(struct ofono_netmon *netmon,
int info_type, ...)
{
va_list arglist;
DBusMessage *agent_notify = NULL;
DBusMessageIter iter;
DBusMessageIter dict;
enum ofono_netmon_info next_info_type = info_type;
@ -79,13 +82,18 @@ void ofono_netmon_serving_cell_notify(struct ofono_netmon *netmon,
char *mcc;
char *mnc;
int intval;
netmon->reply = dbus_message_new_method_return(netmon->pending);
if (netmon->reply == NULL)
if (netmon->pending != NULL) {
netmon->reply = dbus_message_new_method_return(netmon->pending);
dbus_message_iter_init_append(netmon->reply, &iter);
} else if (netmon->agent != NULL) {
agent_notify = netmon_agent_new_method_call(netmon->agent,
"ServingCellInformationChanged");
dbus_message_iter_init_append(agent_notify, &iter);
} else
return;
dbus_message_iter_init_append(netmon->reply, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
OFONO_PROPERTIES_ARRAY_SIGNATURE,
&dict);
@ -243,6 +251,9 @@ done:
va_end(arglist);
dbus_message_iter_close_container(&iter, &dict);
if (agent_notify)
netmon_agent_send_no_reply(netmon->agent, agent_notify);
}
static void serving_cell_info_callback(const struct ofono_error *error,
@ -291,10 +302,117 @@ static DBusMessage *netmon_get_serving_cell_info(DBusConnection *conn,
return NULL;
}
static void periodic_updates_enabled_cb(const struct ofono_error *error,
void *data)
{
struct ofono_netmon *netmon = data;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_error("Error enabling periodic updates");
netmon_agent_free(netmon->agent);
return;
}
}
static void periodic_updates_disabled_cb(const struct ofono_error *error,
void *data)
{
if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
ofono_error("Error disabling periodic updates");
}
static void agent_removed_cb(gpointer user_data)
{
struct ofono_netmon *netmon = user_data;
netmon->agent = NULL;
netmon->driver->enable_periodic_update(netmon, 0, 0,
periodic_updates_disabled_cb,
NULL);
}
static DBusMessage *netmon_register_agent(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_netmon *netmon = data;
const char *agent_path;
const unsigned int enable = 1;
unsigned int period;
if (netmon->agent)
return __ofono_error_busy(msg);
if (!netmon->driver->enable_periodic_update)
return __ofono_error_not_implemented(msg);
if (dbus_message_get_args(msg, NULL,
DBUS_TYPE_OBJECT_PATH, &agent_path,
DBUS_TYPE_UINT32, &period,
DBUS_TYPE_INVALID) == FALSE)
return __ofono_error_invalid_args(msg);
if (!__ofono_dbus_valid_object_path(agent_path))
return __ofono_error_invalid_format(msg);
if (!period)
return __ofono_error_invalid_args(msg);
/* minimum period is 5 seconds, to avoid frequent updates*/
if (period < 5)
period = 5;
netmon->agent = netmon_agent_new(agent_path,
dbus_message_get_sender(msg));
if (netmon->agent == NULL)
return __ofono_error_failed(msg);
netmon_agent_set_removed_notify(netmon->agent, agent_removed_cb, netmon);
netmon->driver->enable_periodic_update(netmon, enable, period,
periodic_updates_enabled_cb, netmon);
return dbus_message_new_method_return(msg);
}
static DBusMessage *netmon_unregister_agent(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_netmon *netmon = data;
const char *agent_path;
const char *agent_bus = dbus_message_get_sender(msg);
if (!netmon->driver->enable_periodic_update)
return __ofono_error_not_implemented(msg);
if (dbus_message_get_args(msg, NULL,
DBUS_TYPE_OBJECT_PATH, &agent_path,
DBUS_TYPE_INVALID) == FALSE)
return __ofono_error_invalid_args(msg);
if (netmon->agent == NULL)
return __ofono_error_failed(msg);
if (!netmon_agent_matches(netmon->agent, agent_path, agent_bus))
return __ofono_error_access_denied(msg);
netmon_agent_free(netmon->agent);
return dbus_message_new_method_return(msg);
}
static const GDBusMethodTable netmon_methods[] = {
{ GDBUS_ASYNC_METHOD("GetServingCellInformation",
NULL, GDBUS_ARGS({ "cellinfo", "a{sv}" }),
netmon_get_serving_cell_info) },
{ GDBUS_METHOD("RegisterAgent",
GDBUS_ARGS({ "path", "o"}, { "period", "u"}), NULL,
netmon_register_agent) },
{ GDBUS_METHOD("UnregisterAgent",
GDBUS_ARGS({ "agent", "o" }), NULL,
netmon_unregister_agent) },
{ }
};

122
src/netmonagent.c Normal file
View File

@ -0,0 +1,122 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <gdbus.h>
#include "ofono.h"
#include "netmonagent.h"
struct netmon_agent {
char *path;
char *bus;
guint disconnect_watch;
ofono_destroy_func removed_cb;
void *removed_data;
};
DBusMessage *netmon_agent_new_method_call(struct netmon_agent *agent,
const char *method)
{
DBusMessage *msg = dbus_message_new_method_call(agent->bus,
agent->path,
OFONO_NETMON_AGENT_INTERFACE,
method);
return msg;
}
void netmon_agent_send_no_reply(struct netmon_agent *agent,
DBusMessage *message)
{
DBusConnection *conn = ofono_dbus_get_connection();
dbus_message_set_no_reply(message, TRUE);
g_dbus_send_message(conn, message);
}
static inline void netmon_agent_send_release(struct netmon_agent *agent)
{
DBusMessage *msg = netmon_agent_new_method_call(agent, "Release");
netmon_agent_send_no_reply(agent, msg);
}
ofono_bool_t netmon_agent_matches(struct netmon_agent *agent,
const char *path, const char *sender)
{
return g_str_equal(agent->path, path) &&
g_str_equal(agent->bus, sender);
}
ofono_bool_t netmon_agent_sender_matches(struct netmon_agent *agent,
const char *sender)
{
return g_str_equal(agent->bus, sender);
}
void netmon_agent_set_removed_notify(struct netmon_agent *agent,
ofono_destroy_func destroy,
void *user_data)
{
agent->removed_cb = destroy;
agent->removed_data = user_data;
}
void netmon_agent_free(struct netmon_agent *agent)
{
DBusConnection *conn = ofono_dbus_get_connection();
if (agent == NULL)
return;
if (agent->disconnect_watch) {
netmon_agent_send_release(agent);
g_dbus_remove_watch(conn, agent->disconnect_watch);
agent->disconnect_watch = 0;
}
if (agent->removed_cb)
agent->removed_cb(agent->removed_data);
g_free(agent->path);
g_free(agent->bus);
g_free(agent);
}
static void netmon_agent_disconnect_cb(DBusConnection *conn, void *user_data)
{
struct netmon_agent *agent = user_data;
ofono_debug("Agent exited without calling UnregisterAgent");
agent->disconnect_watch = 0;
netmon_agent_free(agent);
}
struct netmon_agent *netmon_agent_new(const char *path,
const char *sender)
{
struct netmon_agent *agent = g_try_new0(struct netmon_agent, 1);
DBusConnection *conn = ofono_dbus_get_connection();
if (agent == NULL)
return NULL;
agent->bus = g_strdup(sender);
agent->path = g_strdup(path);
agent->disconnect_watch = g_dbus_add_disconnect_watch(conn, sender,
netmon_agent_disconnect_cb,
agent, NULL);
return agent;
}

23
src/netmonagent.h Normal file
View File

@ -0,0 +1,23 @@
struct netmon_agent;
struct netmon_agent *netmon_agent_new(const char *path, const char *sender);
void netmon_agent_free(struct netmon_agent *agent);
void netmon_agent_set_removed_notify(struct netmon_agent *agent,
ofono_destroy_func removed_cb,
void *user_data);
ofono_bool_t netmon_agent_matches(struct netmon_agent *agent,
const char *path, const char *sender);
ofono_bool_t netmon_agent_sender_matches(struct netmon_agent *agent,
const char *sender);
DBusMessage *netmon_agent_new_method_call(struct netmon_agent *netmon,
const char *method);
void netmon_agent_send_no_reply(struct netmon_agent *agent,
DBusMessage *message);
void netmon_agent_test(struct netmon_agent *agent);

View File

@ -1186,6 +1186,9 @@ static void notify_status_watches(struct ofono_netreg *netreg)
const char *mcc = NULL;
const char *mnc = NULL;
if (netreg->status_watches == NULL)
return;
if (netreg->current_operator) {
mcc = netreg->current_operator->mcc;
mnc = netreg->current_operator->mnc;

View File

@ -15,6 +15,7 @@
<allow send_interface="org.ofono.SmartMessagingAgent"/>
<allow send_interface="org.ofono.PositioningRequestAgent"/>
<allow send_interface="org.ofono.HandsfreeAudioAgent"/>
<allow send_interface="org.ofono.NetworkMonitorAgent"/>
</policy>
<policy at_console="true">

View File

@ -167,7 +167,7 @@ static gboolean radio_band_umts_from_string(const char *str,
enum ofono_radio_band_umts *band)
{
if (g_str_equal(str, "any")) {
*band = OFONO_RADIO_BAND_GSM_ANY;
*band = OFONO_RADIO_BAND_UMTS_ANY;
return TRUE;
} else if (g_str_equal(str, "850")) {
*band = OFONO_RADIO_BAND_UMTS_850;

View File

@ -1171,7 +1171,8 @@ static gboolean compute_incoming_msgid(GSList *sms_list,
static void dispatch_app_datagram(struct ofono_sms *sms,
const struct ofono_uuid *uuid,
int dst, int src,
unsigned char *buf, unsigned len,
const unsigned char *buf,
unsigned int len,
const struct sms_address *addr,
const struct sms_scts *scts)
{

View File

@ -511,6 +511,20 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
ussd_change_state(ussd, new_state);
goto free;
} else if (ussd->state == USSD_STATE_USER_ACTION &&
status != OFONO_USSD_STATUS_ACTION_REQUIRED) {
ussd_change_state(ussd, USSD_STATE_IDLE);
if (status == OFONO_USSD_STATUS_NOTIFY && str && str[0]) {
const char *path = __ofono_atom_get_path(ussd->atom);
g_dbus_emit_signal(conn, path,
OFONO_SUPPLEMENTARY_SERVICES_INTERFACE,
"NotificationReceived", DBUS_TYPE_STRING,
&str, DBUS_TYPE_INVALID);
}
goto free;
} else {
ofono_error("Received an unsolicited USSD but can't handle.");

View File

@ -2252,7 +2252,7 @@ void ofono_voicecall_notify(struct ofono_voicecall *vc,
DBG("Got a voicecall event, status: %s (%d), id: %u, number: %s"
" called_number: %s, called_name %s",
ofono_call_status_to_string(call->status),
call_status_to_string(call->status),
call->status, call->id, call->phone_number.number,
call->called_number.number, call->name);

View File

@ -0,0 +1,97 @@
#!/usr/bin/python3
from gi.repository import GLib
import sys
import dbus
import dbus.service
import dbus.mainloop.glib
NETMON_INTERFACE = "org.ofono.NetworkMonitor"
AGENT_INTERFACE = "org.ofono.NetworkMonitorAgent"
class NetworkMonitorAgent(dbus.service.Object):
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Release(self):
print("Agent Released")
mainloop.quit()
@dbus.service.method(AGENT_INTERFACE,
in_signature="a{sv}", out_signature="")
def ServingCellInformationChanged(self, servingcell):
print("ServingCellInformationChanged notification recieved")
tech = 'Technology'
mcc = 'MobileCountryCode'
mnc = 'MobileNetworkCode'
lac = 'LocationAreaCode'
cid = 'CellId'
psc = 'PrimaryScramblingCode'
rssi = 'Strength'
ber = 'BitErrorRate'
if tech in servingcell:
print(" [ Radio Access Technology = %s]" \
% (servingcell[tech]))
if mcc in servingcell:
print(" [ Mobile Country Code = %s]" \
% (servingcell[mcc]))
if mnc in servingcell:
print(" [ Mobile Network Code = %s]" \
% (servingcell[mnc]))
if lac in servingcell:
print(" [ Location Area Code = %d]" \
% (servingcell[lac]))
if cid in servingcell:
print(" [ Cell Identity = %d]" \
% (servingcell[cid]))
if psc in servingcell:
print(" [ Primary Scrambling Code = %d]" \
% (servingcell[psc]))
if rssi in servingcell:
print(" [ Signal Strength = %d]" \
% (servingcell[rssi]))
if ber in servingcell:
print(" [ Bit Error Rate = %d]" \
% (servingcell[ber]))
print('')
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
if len(sys.argv) < 2:
print("Usage: %s <update_period_in_seconds>" %\
(sys.argv[0]))
sys.exit(1)
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.ofono", "/"),
"org.ofono.Manager")
modems = manager.GetModems()
path = modems[0][0]
nm = dbus.Interface(bus.get_object('org.ofono', path),
NETMON_INTERFACE)
path = "/test/netmonagent"
agent = NetworkMonitorAgent(bus, path)
try:
period = int(sys.argv[1])
except:
print("Error: Invalid argument %s" % (sys.argv[1]))
sys.exit(1)
nm.RegisterAgent(path, period)
print("Agent registered")
mainloop = GLib.MainLoop()
mainloop.run()

View File

@ -178,12 +178,12 @@ static void test_ber_tlv_builder_efpnn(void)
ber_tlv_builder_optimize(&builder, NULL, NULL);
eons_info = sim_eons_new(1);
sim_eons_add_pnn_record(eons_info, 1, efpnn0, sizeof(efpnn0));
sim_eons_add_pnn_record(eons_info, 1, efpnn0, 8 + 10);
g_assert(!sim_eons_pnn_is_empty(eons_info));
sim_eons_free(eons_info);
eons_info = sim_eons_new(1);
sim_eons_add_pnn_record(eons_info, 1, efpnn1, sizeof(efpnn1));
sim_eons_add_pnn_record(eons_info, 1, efpnn1, 8 + 6);
g_assert(!sim_eons_pnn_is_empty(eons_info));
sim_eons_free(eons_info);
}