Commit a76f50be authored by Slava Monich's avatar Slava Monich

Merge branch 'vendor_signal' into 'master'

Add vendor-specific parsing of SIGNAL_STRENGTH messages

See merge request !242
parents e40811fb 43227086
......@@ -20,6 +20,7 @@
#include "ril_sim_card.h"
#include "ril_sim_settings.h"
#include "ril_cell_info.h"
#include "ril_vendor.h"
#include "ril_data.h"
#include "ril_util.h"
#include "ril_log.h"
......@@ -435,6 +436,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
g_source_remove(md->set_offline.timeout_id);
}
ril_vendor_unref(modem->vendor);
ril_network_unref(modem->network);
ril_sim_card_unref(modem->sim_card);
ril_data_unref(modem->data);
......@@ -456,7 +458,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const char *ecclist_file, const struct ril_slot_config *config,
struct ril_radio *radio, struct ril_network *network,
struct ril_sim_card *card, struct ril_data *data,
struct ril_sim_settings *settings,
struct ril_sim_settings *settings, struct ril_vendor *vendor,
struct sailfish_cell_info *cell_info)
{
/* Skip the slash from the path, it looks like "/ril_0" */
......@@ -483,6 +485,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
modem->ofono = ofono;
modem->vendor = ril_vendor_ref(vendor);
modem->radio = ril_radio_ref(radio);
modem->network = ril_network_ref(network);
modem->sim_card = ril_sim_card_ref(card);
......
......@@ -2,6 +2,7 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
......@@ -16,6 +17,7 @@
#include "ril_plugin.h"
#include "ril_network.h"
#include "ril_util.h"
#include "ril_vendor.h"
#include "ril_log.h"
#include "common.h"
......@@ -42,6 +44,7 @@ struct ril_netreg {
gboolean network_selection_manual_0;
struct ofono_netreg *netreg;
struct ril_network *network;
struct ril_vendor *vendor;
char *log_prefix;
guint timer_id;
guint notify_id;
......@@ -331,100 +334,92 @@ static void ril_netreg_register_manual(struct ofono_netreg *netreg,
grilio_request_unref(req);
}
static int ril_netreg_dbm_to_percentage(int dbm)
static int ril_netreg_qdbm_to_percentage(int qdbm /* 4*dBm */)
{
const int min_dbm = -100; /* very weak signal, 0.0000000001 mW */
const int max_dbm = -60; /* strong signal, 0.000001 mW */
const int min_qdbm = -4*100; /* very weak signal, 0.0000000001 mW */
const int max_qdbm = -4*60; /* strong signal, 0.000001 mW */
return (dbm <= min_dbm) ? 1 :
(dbm >= max_dbm) ? 100 :
(100 * (dbm - min_dbm) / (max_dbm - min_dbm));
return (qdbm <= min_qdbm) ? 1 :
(qdbm >= max_qdbm) ? 100 :
(100 * (qdbm - min_qdbm) / (max_qdbm - min_qdbm));
}
static int ril_netreg_get_signal_strength(const void *data, guint len)
static int ril_netreg_get_signal_strength(struct ril_vendor *vendor,
const void *data, guint len)
{
GRilIoParser rilp;
int gw_signal = 0, cdma_dbm = 0, evdo_dbm = 0, lte_signal = 0;
int rsrp = 0, tdscdma_dbm = 0;
struct ril_vendor_signal_strength signal;
grilio_parser_init(&rilp, data, len);
/* GW_SignalStrength */
grilio_parser_get_int32(&rilp, &gw_signal);
grilio_parser_get_int32(&rilp, NULL); /* bitErrorRate */
/* CDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &cdma_dbm);
grilio_parser_get_int32(&rilp, NULL); /* ecio */
/* EVDO_SignalStrength */
grilio_parser_get_int32(&rilp, &evdo_dbm);
grilio_parser_get_int32(&rilp, NULL); /* ecio */
grilio_parser_get_int32(&rilp, NULL); /* signalNoiseRatio */
/* LTE_SignalStrength */
grilio_parser_get_int32(&rilp, &lte_signal);
grilio_parser_get_int32(&rilp, &rsrp);
/* Skip the rest of LTE_SignalStrength_v8 */
if (grilio_parser_get_int32(&rilp, NULL) && /* rsrq */
grilio_parser_get_int32(&rilp, NULL) && /* rssnr */
grilio_parser_get_int32(&rilp, NULL) && /* cqi */
grilio_parser_get_int32(&rilp, NULL)) { /* timingAdvance */
/* TD_SCDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &tdscdma_dbm); /* rscp */
signal.gsm = INT_MAX;
signal.lte = INT_MAX;
signal.qdbm = 0;
if (!ril_vendor_signal_strength_parse(vendor, &signal, &rilp)) {
gint32 rsrp = 0, tdscdma_dbm = 0;
/* Apply default parsing algorithm */
grilio_parser_init(&rilp, data, len);
signal.gsm = INT_MAX;
signal.lte = INT_MAX;
signal.qdbm = 0;
/* GW_SignalStrength */
grilio_parser_get_int32(&rilp, &signal.gsm);
grilio_parser_get_int32(&rilp, NULL); /* bitErrorRate */
/* CDMA_SignalStrength */
grilio_parser_get_int32(&rilp, NULL); /* dbm */
grilio_parser_get_int32(&rilp, NULL); /* ecio */
/* EVDO_SignalStrength */
grilio_parser_get_int32(&rilp, NULL); /* dbm */
grilio_parser_get_int32(&rilp, NULL); /* ecio */
grilio_parser_get_int32(&rilp, NULL); /* signalNoiseRatio */
/* LTE_SignalStrength */
grilio_parser_get_int32(&rilp, &signal.lte);
grilio_parser_get_int32(&rilp, &rsrp);
/* The rest is considered optional */
if (grilio_parser_get_int32(&rilp, NULL) && /* rsrq */
grilio_parser_get_int32(&rilp, NULL) && /* rssnr */
grilio_parser_get_int32(&rilp, NULL) && /* cqi */
grilio_parser_get_int32(&rilp, NULL) && /* timingAdv */
/* TD_SCDMA_SignalStrength */
grilio_parser_get_int32(&rilp, &tdscdma_dbm) &&
/* RSCP range: 25 to 120 dBm per 3GPP TS 25.123 */
tdscdma_dbm >= 25 && tdscdma_dbm <= 120) {
signal.qdbm = -4 * tdscdma_dbm;
} else if (signal.lte == 99 && rsrp >= 44 && rsrp <= 140) {
/* RSRP range: 44 to 140 dBm per 3GPP TS 36.133 */
signal.qdbm = -rsrp;
}
}
if (rsrp == INT_MAX) {
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d, tdscdma: %d",
gw_signal, cdma_dbm, evdo_dbm,
lte_signal, tdscdma_dbm);
} else {
DBG("gw: %d, cdma: %d, evdo: %d, lte: %d rsrp: %d, tdscdma: %d",
gw_signal, cdma_dbm, evdo_dbm,
lte_signal, rsrp, tdscdma_dbm);
}
DBG("gw: %d, lte: %d, qdbm: %d", signal.gsm, signal.lte, signal.qdbm);
/* Return the first valid one */
/* Some RILs (namely, from MediaTek) report 0 here AND a valid LTE
* RSRP value. If we've got zero, don't report it just yet. */
if (gw_signal >= 1 && gw_signal <= 31) {
if (signal.gsm >= 1 && signal.gsm <= 31) {
/* Valid values are (0-31, 99) as defined in TS 27.007 */
return (gw_signal * 100) / 31;
return (signal.gsm * 100) / 31;
}
/* Valid values are (0-31, 99) as defined in TS 27.007 */
if (lte_signal >= 0 && lte_signal <= 31) {
return (lte_signal * 100) / 31;
}
/* RSCP range: 25 to 120 dBm as defined in 3GPP TS 25.123 */
if (tdscdma_dbm >= 25 && tdscdma_dbm <= 120) {
return ril_netreg_dbm_to_percentage(-tdscdma_dbm);
if (signal.lte >= 0 && signal.lte <= 31) {
return (signal.lte * 100) / 31;
}
/* RSRP range: 44 to 140 dBm as defined in 3GPP TS 36.133 */
if (lte_signal == 99 && rsrp >= 44 && rsrp <= 140) {
return ril_netreg_dbm_to_percentage(-rsrp);
}
/* If we've got zero strength and no valid RSRP, then so be it */
if (gw_signal == 0) {
if (signal.qdbm < 0) {
return ril_netreg_qdbm_to_percentage(signal.qdbm);
} else if (signal.gsm == 0) {
return 0;
} else {
return -1;
}
/* In case of dbm, return the value directly */
if (cdma_dbm != -1) {
return MIN(cdma_dbm, 100);
}
if (evdo_dbm != -1) {
return MIN(evdo_dbm, 100);
}
return -1;
}
static void ril_netreg_strength_notify(GRilIoChannel *io, guint ril_event,
......@@ -434,9 +429,11 @@ static void ril_netreg_strength_notify(GRilIoChannel *io, guint ril_event,
int strength;
GASSERT(ril_event == RIL_UNSOL_SIGNAL_STRENGTH);
strength = ril_netreg_get_signal_strength(data, len);
strength = ril_netreg_get_signal_strength(nd->vendor, data, len);
DBG_(nd, "%d", strength);
ofono_netreg_strength_notify(nd->netreg, strength);
if (strength >= 0) {
ofono_netreg_strength_notify(nd->netreg, strength);
}
}
static void ril_netreg_strength_cb(GRilIoChannel *io, int status,
......@@ -447,8 +444,8 @@ static void ril_netreg_strength_cb(GRilIoChannel *io, int status,
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
int strength = ril_netreg_get_signal_strength(data, len);
cb(ril_error_ok(&error), strength, cbd->data);
cb(ril_error_ok(&error), ril_netreg_get_signal_strength
(cbd->nd->vendor, data, len), cbd->data);
} else {
ofono_error("Failed to retrive the signal strength: %s",
ril_error_to_string(status));
......@@ -558,6 +555,7 @@ static int ril_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor,
DBG_(nd, "%p", netreg);
nd->io = grilio_channel_ref(ril_modem_io(modem));
nd->q = grilio_queue_new(nd->io);
nd->vendor = ril_vendor_ref(modem->vendor);
nd->network = ril_network_ref(modem->network);
nd->netreg = netreg;
nd->network_selection_manual_0 = config->network_selection_manual_0;
......@@ -589,6 +587,7 @@ static void ril_netreg_remove(struct ofono_netreg *netreg)
ril_network_remove_all_handlers(nd->network, nd->network_event_id);
ril_network_unref(nd->network);
ril_vendor_unref(nd->vendor);
grilio_channel_remove_all_handlers(nd->io, nd->ril_event_id);
grilio_channel_unref(nd->io);
......
......@@ -838,7 +838,7 @@ static void ril_plugin_create_modem(ril_slot *slot)
modem = ril_modem_create(slot->io, log_prefix, slot->path, slot->imei,
slot->imeisv, slot->ecclist_file, &slot->config, slot->radio,
slot->network, slot->sim_card, slot->data, slot->sim_settings,
slot->cell_info);
slot->vendor, slot->cell_info);
if (modem) {
slot->modem = modem;
......
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2017 Jolla Ltd.
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
......@@ -52,6 +53,7 @@ struct ril_modem {
const char *ecclist_file;
struct ofono_modem *ofono;
struct sailfish_cell_info *cell_info;
struct ril_vendor *vendor;
struct ril_radio *radio;
struct ril_data *data;
struct ril_network *network;
......@@ -70,7 +72,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const char *ecclist_file, const struct ril_slot_config *config,
struct ril_radio *radio, struct ril_network *network,
struct ril_sim_card *card, struct ril_data *data,
struct ril_sim_settings *settings,
struct ril_sim_settings *settings, struct ril_vendor *vendor,
struct sailfish_cell_info *cell_info);
void ril_modem_delete(struct ril_modem *modem);
struct ofono_sim *ril_modem_ofono_sim(struct ril_modem *modem);
......
......@@ -2,6 +2,7 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
......@@ -116,6 +117,14 @@ gboolean ril_vendor_data_call_parse(RilVendor *self,
data_call_parse(self, call, ver, rilp);
}
gboolean ril_vendor_signal_strength_parse(RilVendor *self,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp)
{
return G_LIKELY(self) && RIL_VENDOR_GET_CLASS(self)->
signal_strength_parse(self, signal_strength, rilp);
}
static void ril_vendor_default_set_network(RilVendor *self,
struct ril_network *network)
{
......@@ -160,6 +169,13 @@ static gboolean ril_vendor_default_data_call_parse(RilVendor *self,
return FALSE;
}
static gboolean ril_vendor_default_signal_strength_parse(RilVendor *self,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp)
{
return FALSE;
}
void ril_vendor_init_base(RilVendor *self, GRilIoChannel *io)
{
self->io = grilio_channel_ref(io);
......@@ -190,6 +206,7 @@ static void ril_vendor_class_init(RilVendorClass* klass)
klass->set_attach_apn_req = ril_vendor_default_set_attach_apn_req;
klass->data_call_req = ril_vendor_default_data_call_req;
klass->data_call_parse = ril_vendor_default_data_call_parse;
klass->signal_strength_parse = ril_vendor_default_signal_strength_parse;
}
/*
......
......@@ -39,6 +39,12 @@ struct ril_vendor_driver {
const struct ril_slot_config *cfg);
};
struct ril_vendor_signal_strength {
gint32 gsm; /* (0-31, 99) per TS 27.007 8.5 */
gint32 lte; /* (0-31, 99) per TS 27.007 8.5 */
gint32 qdbm; /* 4*dBm, 0 if none */
};
const struct ril_vendor_driver *ril_vendor_find_driver(const char *name);
struct ril_vendor *ril_vendor_create
(const struct ril_vendor_driver *vendor, GRilIoChannel *io,
......@@ -65,6 +71,9 @@ GRilIoRequest *ril_vendor_data_call_req(struct ril_vendor *vendor, int tech,
gboolean ril_vendor_data_call_parse(struct ril_vendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
gboolean ril_vendor_signal_strength_parse(struct ril_vendor *vendor,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp);
/* Put vendor driver descriptors to the "__vendor" section */
#define RIL_VENDOR_DRIVER_DEFINE(name) const struct ril_vendor_driver name \
......
......@@ -2,6 +2,7 @@
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2019 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* 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
......@@ -42,6 +43,9 @@ typedef struct ril_vendor_class {
gboolean (*data_call_parse)(RilVendor *vendor,
struct ril_data_call *call, int version,
GRilIoParser *rilp);
gboolean (*signal_strength_parse)(RilVendor *vendor,
struct ril_vendor_signal_strength *signal_strength,
GRilIoParser *rilp);
} RilVendorClass;
GType ril_vendor_get_type(void);
......
......@@ -80,6 +80,8 @@ struct ril_mtk_flavor {
enum ril_auth auth, const char *proto);
gboolean (*data_call_parse_fn)(struct ril_data_call *call,
int version, GRilIoParser *rilp);
gboolean (*signal_strength_fn)(struct ril_vendor_signal_strength *sig,
GRilIoParser *rilp);
};
/* MTK specific RIL messages (actual codes differ from model to model!) */
......@@ -402,6 +404,96 @@ static gboolean ril_vendor_mtk_data_call_parse(RilVendor *vendor,
data_call_parse(vendor, call, version, rilp);
}
static gboolean ril_vendor_mtk_signal_strength_1
(struct ril_vendor_signal_strength *signal, GRilIoParser *rilp)
{
if (grilio_parser_bytes_remaining(rilp) == 64) {
gint32 rsrp = 0, rssi = 0;
/* GW_SignalStrength */
grilio_parser_get_int32(rilp, &signal->gsm);
grilio_parser_get_int32(rilp, NULL); /* bitErrorRate */
/* CDMA_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
/* EVDO_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
grilio_parser_get_int32(rilp, NULL); /* signalNoiseRatio */
/* LTE_SignalStrength */
grilio_parser_get_int32(rilp, &signal->lte);
grilio_parser_get_int32(rilp, &rsrp); /* rsrp */
grilio_parser_get_int32(rilp, NULL); /* rsrq */
grilio_parser_get_int32(rilp, NULL); /* rssnr */
grilio_parser_get_int32(rilp, NULL); /* cqi */
/* ???? */
grilio_parser_get_int32(rilp, NULL);
grilio_parser_get_int32(rilp, &rssi);
grilio_parser_get_int32(rilp, NULL);
grilio_parser_get_int32(rilp, NULL);
signal->qdbm = (rssi > 0 && rssi != INT_MAX) ? (-4 * rssi) :
(rsrp >= 44 && rsrp <= 140) ? (-4 * rsrp) : 0;
return TRUE;
}
return FALSE;
}
static gboolean ril_vendor_mtk_signal_strength_2
(struct ril_vendor_signal_strength *signal, GRilIoParser *rilp)
{
if (grilio_parser_bytes_remaining(rilp) == 64) {
gint32 rsrp = 0, is_gsm = 0, rssi_qdbm = 0;
/* GW_SignalStrength */
grilio_parser_get_int32(rilp, &signal->gsm);
grilio_parser_get_int32(rilp, NULL); /* bitErrorRate */
/* CDMA_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
/* EVDO_SignalStrength */
grilio_parser_get_int32(rilp, NULL); /* dbm */
grilio_parser_get_int32(rilp, NULL); /* ecio */
grilio_parser_get_int32(rilp, NULL); /* signalNoiseRatio */
/* LTE_SignalStrength */
grilio_parser_get_int32(rilp, &signal->lte);
grilio_parser_get_int32(rilp, &rsrp); /* rsrp */
grilio_parser_get_int32(rilp, NULL); /* rsrq */
grilio_parser_get_int32(rilp, NULL); /* rssnr */
grilio_parser_get_int32(rilp, NULL); /* cqi */
/* WCDMA_SignalStrength */
grilio_parser_get_int32(rilp, &is_gsm); /* isGsm */
grilio_parser_get_int32(rilp, &rssi_qdbm); /* rssiQdbm */
grilio_parser_get_int32(rilp, NULL); /* rscpQdbm */
grilio_parser_get_int32(rilp, NULL); /* Ecn0Qdbm*/
signal->qdbm = (is_gsm == 1 && rssi_qdbm < 0) ? rssi_qdbm :
(rsrp >= 44 && rsrp <= 140) ? (-4 * rsrp) : 0;
return TRUE;
}
return FALSE;
}
static gboolean ril_vendor_mtk_signal_strength_parse(RilVendor *vendor,
struct ril_vendor_signal_strength *signal,
GRilIoParser *rilp)
{
const struct ril_mtk_flavor *flavor = RIL_VENDOR_MTK(vendor)->flavor;
return flavor->signal_strength_fn ?
flavor->signal_strength_fn(signal, rilp) :
RIL_VENDOR_CLASS(ril_vendor_mtk_parent_class)->
signal_strength_parse(vendor, signal, rilp);
}
static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
{
/*
......@@ -498,20 +590,23 @@ static void ril_vendor_mtk_class_init(RilVendorMtkClass* klass)
klass->set_attach_apn_req = ril_vendor_mtk_set_attach_apn_req;
klass->data_call_req = ril_vendor_mtk_data_call_req;
klass->data_call_parse = ril_vendor_mtk_data_call_parse;
klass->signal_strength_parse = ril_vendor_mtk_signal_strength_parse;
}
static const struct ril_mtk_flavor ril_mtk_flavor1 = {
.name = "mtk1",
.msg = &msg_mtk1,
.build_attach_apn_req_fn = &ril_vendor_mtk_build_attach_apn_req_1,
.data_call_parse_fn = NULL
.data_call_parse_fn = NULL,
.signal_strength_fn = &ril_vendor_mtk_signal_strength_1
};
static const struct ril_mtk_flavor ril_mtk_flavor2 = {
.name = "mtk2",
.msg = &msg_mtk2,
.build_attach_apn_req_fn = &ril_vendor_mtk_build_attach_apn_req_2,
.data_call_parse_fn = &ril_vendor_mtk_data_call_parse_v6
.data_call_parse_fn = &ril_vendor_mtk_data_call_parse_v6,
.signal_strength_fn = &ril_vendor_mtk_signal_strength_2
};
#define DEFAULT_MTK_TYPE (&ril_mtk_flavor1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment