forked from sailfishos/ofono
		
	[ril] Add a new device state management method. JB#49175
If applied, this commit will add a new ril_devmon implementation which controls network state updates by sending SET_UNSOLICITED_RESPONSE_FILTER. This is useful for devices with RIL version >= 15 if they ignore both SEND_DEVICE_STATE and SEND_SCREEN_STATE requests as some Qualcomm- based devices do.
This commit is contained in:
		@@ -153,6 +153,7 @@ builtin_sources +=	drivers/ril/ril_call_barring.c \
 | 
			
		||||
			drivers/ril/ril_devmon_auto.c \
 | 
			
		||||
			drivers/ril/ril_devmon_ds.c \
 | 
			
		||||
			drivers/ril/ril_devmon_ss.c \
 | 
			
		||||
			drivers/ril/ril_devmon_ur.c \
 | 
			
		||||
			drivers/ril/ril_ecclist.c \
 | 
			
		||||
			drivers/ril/ril_gprs.c \
 | 
			
		||||
			drivers/ril/ril_gprs_context.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -375,6 +375,13 @@ enum ril_restricted_state {
 | 
			
		||||
#define RIL_FACILITY_UNLOCK "0"
 | 
			
		||||
#define RIL_FACILITY_LOCK "1"
 | 
			
		||||
 | 
			
		||||
/* See RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER (RIL_VERSION >= 15) */
 | 
			
		||||
enum  ril_unsolicited_response_filter {
 | 
			
		||||
	RIL_UR_SIGNAL_STRENGTH            = 0x01,
 | 
			
		||||
	RIL_UR_FULL_NETWORK_STATE         = 0x02,
 | 
			
		||||
	RIL_UR_DATA_CALL_DORMANCY_CHANGED = 0x04
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /*__RIL_CONSTANTS_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,12 @@ struct ril_devmon *ril_devmon_ss_new(void);
 | 
			
		||||
 */
 | 
			
		||||
struct ril_devmon *ril_devmon_ds_new(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This Device Monitor implementation controls network state updates
 | 
			
		||||
 * by sending SET_UNSOLICITED_RESPONSE_FILTER.
 | 
			
		||||
 */
 | 
			
		||||
struct ril_devmon *ril_devmon_ur_new(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This one selects the type based on the RIL version.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										254
									
								
								ofono/drivers/ril/ril_devmon_ur.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								ofono/drivers/ril/ril_devmon_ur.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  oFono - Open Source Telephony - RIL-based devices
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2019 Jolla Ltd.
 | 
			
		||||
 *  Copyright (C) 2020 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
 | 
			
		||||
 *  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_devmon.h"
 | 
			
		||||
 | 
			
		||||
#include <ofono/log.h>
 | 
			
		||||
#include <ofono/ril-constants.h>
 | 
			
		||||
 | 
			
		||||
#include <mce_battery.h>
 | 
			
		||||
#include <mce_charger.h>
 | 
			
		||||
#include <mce_display.h>
 | 
			
		||||
 | 
			
		||||
#include <grilio_channel.h>
 | 
			
		||||
#include <grilio_request.h>
 | 
			
		||||
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
 | 
			
		||||
#define RIL_UR_ENABLE_ALL	(RIL_UR_SIGNAL_STRENGTH | \
 | 
			
		||||
				RIL_UR_FULL_NETWORK_STATE | \
 | 
			
		||||
				RIL_UR_DATA_CALL_DORMANCY_CHANGED)
 | 
			
		||||
 | 
			
		||||
enum ril_devmon_ur_battery_event {
 | 
			
		||||
	BATTERY_EVENT_VALID,
 | 
			
		||||
	BATTERY_EVENT_STATUS,
 | 
			
		||||
	BATTERY_EVENT_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ril_devmon_ur_charger_event {
 | 
			
		||||
	CHARGER_EVENT_VALID,
 | 
			
		||||
	CHARGER_EVENT_STATE,
 | 
			
		||||
	CHARGER_EVENT_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ril_devmon_ur_display_event {
 | 
			
		||||
	DISPLAY_EVENT_VALID,
 | 
			
		||||
	DISPLAY_EVENT_STATE,
 | 
			
		||||
	DISPLAY_EVENT_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct ril_devmon_ur {
 | 
			
		||||
	struct ril_devmon pub;
 | 
			
		||||
	MceBattery *battery;
 | 
			
		||||
	MceCharger *charger;
 | 
			
		||||
	MceDisplay *display;
 | 
			
		||||
} DevMon;
 | 
			
		||||
 | 
			
		||||
typedef struct ril_devmon_ur_io {
 | 
			
		||||
	struct ril_devmon_io pub;
 | 
			
		||||
	struct sailfish_cell_info *cell_info;
 | 
			
		||||
	MceBattery *battery;
 | 
			
		||||
	MceCharger *charger;
 | 
			
		||||
	MceDisplay *display;
 | 
			
		||||
	GRilIoChannel *io;
 | 
			
		||||
	gboolean display_on;
 | 
			
		||||
	gboolean unsol_filter_supported;
 | 
			
		||||
	gulong battery_event_id[BATTERY_EVENT_COUNT];
 | 
			
		||||
	gulong charger_event_id[CHARGER_EVENT_COUNT];
 | 
			
		||||
	gulong display_event_id[DISPLAY_EVENT_COUNT];
 | 
			
		||||
	guint req_id;
 | 
			
		||||
} DevMonIo;
 | 
			
		||||
 | 
			
		||||
#define DBG_(self,fmt,args...) DBG("%s: " fmt, (self)->io->name, ##args)
 | 
			
		||||
 | 
			
		||||
inline static DevMon *ril_devmon_ur_cast(struct ril_devmon *pub)
 | 
			
		||||
{
 | 
			
		||||
	return G_CAST(pub, DevMon, pub);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline static DevMonIo *ril_devmon_ur_io_cast(struct ril_devmon_io *pub)
 | 
			
		||||
{
 | 
			
		||||
	return G_CAST(pub, DevMonIo, pub);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline gboolean ril_devmon_ur_battery_ok(MceBattery *battery)
 | 
			
		||||
{
 | 
			
		||||
	return battery->valid && battery->status >= MCE_BATTERY_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline gboolean ril_devmon_ur_charging(MceCharger *charger)
 | 
			
		||||
{
 | 
			
		||||
	return charger->valid && charger->state == MCE_CHARGER_ON;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean ril_devmon_ur_display_on(MceDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
	return display->valid && display->state != MCE_DISPLAY_STATE_OFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_unsol_response_filter_sent(GRilIoChannel *io,
 | 
			
		||||
				int status, const void *data, guint len,
 | 
			
		||||
				void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	DevMonIo *self = user_data;
 | 
			
		||||
 | 
			
		||||
	self->req_id = 0;
 | 
			
		||||
	if (status == RIL_E_REQUEST_NOT_SUPPORTED) {
 | 
			
		||||
		/* This is a permanent failure */
 | 
			
		||||
		DBG_(self, "Unsolicited response filter is not supported");
 | 
			
		||||
		self->unsol_filter_supported = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_set_unsol_response_filter(DevMonIo *self)
 | 
			
		||||
{
 | 
			
		||||
	if (self->unsol_filter_supported) {
 | 
			
		||||
		const gint32 value = self->display_on ? RIL_UR_ENABLE_ALL : 0;
 | 
			
		||||
		GRilIoRequest *req = grilio_request_array_int32_new(1, value);
 | 
			
		||||
 | 
			
		||||
		DBG_(self, "Setting unsolicited response filter: %u", value);
 | 
			
		||||
 | 
			
		||||
		grilio_channel_cancel_request(self->io, self->req_id, FALSE);
 | 
			
		||||
		self->req_id =
 | 
			
		||||
			grilio_channel_send_request_full(self->io, req,
 | 
			
		||||
				RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER,
 | 
			
		||||
				ril_devmon_ur_io_unsol_response_filter_sent,
 | 
			
		||||
				NULL, self);
 | 
			
		||||
		grilio_request_unref(req);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_set_cell_info_update_interval(DevMonIo *self)
 | 
			
		||||
{
 | 
			
		||||
	sailfish_cell_info_set_update_interval(self->cell_info,
 | 
			
		||||
		(self->display_on && (ril_devmon_ur_charging(self->charger) ||
 | 
			
		||||
				ril_devmon_ur_battery_ok(self->battery))) ?
 | 
			
		||||
					RIL_CELL_INFO_INTERVAL_SHORT_MS :
 | 
			
		||||
					RIL_CELL_INFO_INTERVAL_LONG_MS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_battery_cb(MceBattery *battery, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	ril_devmon_ur_io_set_cell_info_update_interval(user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_charger_cb(MceCharger *charger, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	ril_devmon_ur_io_set_cell_info_update_interval(user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_display_cb(MceDisplay *display, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	DevMonIo *self = user_data;
 | 
			
		||||
	const gboolean display_on = ril_devmon_ur_display_on(display);
 | 
			
		||||
 | 
			
		||||
	if (self->display_on != display_on) {
 | 
			
		||||
		self->display_on = display_on;
 | 
			
		||||
		ril_devmon_ur_io_set_unsol_response_filter(self);
 | 
			
		||||
		ril_devmon_ur_io_set_cell_info_update_interval(self);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_io_free(struct ril_devmon_io *devmon_io)
 | 
			
		||||
{
 | 
			
		||||
	DevMonIo *self = ril_devmon_ur_io_cast(devmon_io);
 | 
			
		||||
 | 
			
		||||
	mce_battery_remove_all_handlers(self->battery, self->battery_event_id);
 | 
			
		||||
	mce_battery_unref(self->battery);
 | 
			
		||||
 | 
			
		||||
	mce_charger_remove_all_handlers(self->charger, self->charger_event_id);
 | 
			
		||||
	mce_charger_unref(self->charger);
 | 
			
		||||
 | 
			
		||||
	mce_display_remove_all_handlers(self->display, self->display_event_id);
 | 
			
		||||
	mce_display_unref(self->display);
 | 
			
		||||
 | 
			
		||||
	grilio_channel_cancel_request(self->io, self->req_id, FALSE);
 | 
			
		||||
	grilio_channel_unref(self->io);
 | 
			
		||||
 | 
			
		||||
	sailfish_cell_info_unref(self->cell_info);
 | 
			
		||||
	g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct ril_devmon_io *ril_devmon_ur_start_io(struct ril_devmon *devmon,
 | 
			
		||||
		GRilIoChannel *io, struct sailfish_cell_info *cell_info)
 | 
			
		||||
{
 | 
			
		||||
	DevMon *ur = ril_devmon_ur_cast(devmon);
 | 
			
		||||
	DevMonIo *self = g_new0(DevMonIo, 1);
 | 
			
		||||
 | 
			
		||||
	self->pub.free = ril_devmon_ur_io_free;
 | 
			
		||||
	self->unsol_filter_supported = TRUE;
 | 
			
		||||
	self->io = grilio_channel_ref(io);
 | 
			
		||||
	self->cell_info = sailfish_cell_info_ref(cell_info);
 | 
			
		||||
 | 
			
		||||
	self->battery = mce_battery_ref(ur->battery);
 | 
			
		||||
	self->battery_event_id[BATTERY_EVENT_VALID] =
 | 
			
		||||
		mce_battery_add_valid_changed_handler(self->battery,
 | 
			
		||||
			ril_devmon_ur_io_battery_cb, self);
 | 
			
		||||
	self->battery_event_id[BATTERY_EVENT_STATUS] =
 | 
			
		||||
		mce_battery_add_status_changed_handler(self->battery,
 | 
			
		||||
			ril_devmon_ur_io_battery_cb, self);
 | 
			
		||||
 | 
			
		||||
	self->charger = mce_charger_ref(ur->charger);
 | 
			
		||||
	self->charger_event_id[CHARGER_EVENT_VALID] =
 | 
			
		||||
		mce_charger_add_valid_changed_handler(self->charger,
 | 
			
		||||
			ril_devmon_ur_io_charger_cb, self);
 | 
			
		||||
	self->charger_event_id[CHARGER_EVENT_STATE] =
 | 
			
		||||
		mce_charger_add_state_changed_handler(self->charger,
 | 
			
		||||
			ril_devmon_ur_io_charger_cb, self);
 | 
			
		||||
 | 
			
		||||
	self->display = mce_display_ref(ur->display);
 | 
			
		||||
	self->display_on = ril_devmon_ur_display_on(self->display);
 | 
			
		||||
	self->display_event_id[DISPLAY_EVENT_VALID] =
 | 
			
		||||
		mce_display_add_valid_changed_handler(self->display,
 | 
			
		||||
			ril_devmon_ur_io_display_cb, self);
 | 
			
		||||
	self->display_event_id[DISPLAY_EVENT_STATE] =
 | 
			
		||||
		mce_display_add_state_changed_handler(self->display,
 | 
			
		||||
			ril_devmon_ur_io_display_cb, self);
 | 
			
		||||
 | 
			
		||||
	ril_devmon_ur_io_set_unsol_response_filter(self);
 | 
			
		||||
	ril_devmon_ur_io_set_cell_info_update_interval(self);
 | 
			
		||||
	return &self->pub;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ril_devmon_ur_free(struct ril_devmon *devmon)
 | 
			
		||||
{
 | 
			
		||||
	DevMon *self = ril_devmon_ur_cast(devmon);
 | 
			
		||||
 | 
			
		||||
	mce_battery_unref(self->battery);
 | 
			
		||||
	mce_charger_unref(self->charger);
 | 
			
		||||
	mce_display_unref(self->display);
 | 
			
		||||
	g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ril_devmon *ril_devmon_ur_new()
 | 
			
		||||
{
 | 
			
		||||
	DevMon *self = g_new0(DevMon, 1);
 | 
			
		||||
 | 
			
		||||
	self->pub.free = ril_devmon_ur_free;
 | 
			
		||||
	self->pub.start_io = ril_devmon_ur_start_io;
 | 
			
		||||
	self->battery = mce_battery_new();
 | 
			
		||||
	self->charger = mce_charger_new();
 | 
			
		||||
	self->display = mce_display_new();
 | 
			
		||||
	return &self->pub;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 8
 | 
			
		||||
 * indent-tabs-mode: t
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -182,7 +182,8 @@ enum ril_devmon_opt {
 | 
			
		||||
	RIL_DEVMON_NONE,
 | 
			
		||||
	RIL_DEVMON_AUTO,
 | 
			
		||||
	RIL_DEVMON_SS,
 | 
			
		||||
	RIL_DEVMON_DS
 | 
			
		||||
	RIL_DEVMON_DS,
 | 
			
		||||
	RIL_DEVMON_UR
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ril_plugin_identity {
 | 
			
		||||
@@ -1710,11 +1711,13 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
 | 
			
		||||
				"none", RIL_DEVMON_NONE,
 | 
			
		||||
				"auto", RIL_DEVMON_AUTO,
 | 
			
		||||
				"ds", RIL_DEVMON_DS,
 | 
			
		||||
				"ss", RIL_DEVMON_SS, NULL)) {
 | 
			
		||||
				"ss", RIL_DEVMON_SS,
 | 
			
		||||
				"ur", RIL_DEVMON_UR, NULL)) {
 | 
			
		||||
		DBG("%s: " RILCONF_DEVMON " %s", group,
 | 
			
		||||
				ival == RIL_DEVMON_NONE ? "off" :
 | 
			
		||||
				ival == RIL_DEVMON_DS ? "on" :
 | 
			
		||||
				ival == RIL_DEVMON_SS ? "legacy" :
 | 
			
		||||
				ival == RIL_DEVMON_UR ? "filter" :
 | 
			
		||||
				"auto");
 | 
			
		||||
		if (ival != RIL_DEVMON_AUTO) {
 | 
			
		||||
			/* Default is automatic, reallocate the object */
 | 
			
		||||
@@ -1722,6 +1725,7 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
 | 
			
		||||
			slot->devmon =
 | 
			
		||||
				(ival == RIL_DEVMON_DS ? ril_devmon_ds_new() :
 | 
			
		||||
				 ival == RIL_DEVMON_SS ? ril_devmon_ss_new() :
 | 
			
		||||
				 ival == RIL_DEVMON_UR ? ril_devmon_ur_new() :
 | 
			
		||||
				 NULL);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -302,7 +302,10 @@ socket=/dev/socket/rild
 | 
			
		||||
#
 | 
			
		||||
#   ss = Use legacy device state management (RIL_REQUEST_SCREEN_STATE)
 | 
			
		||||
#   ds = Use newer device state management (RIL_REQUEST_SEND_DEVICE_STATE)
 | 
			
		||||
#   auto = Choose one of the above based on the RIL version
 | 
			
		||||
#   ur = Use URC filter (RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER)
 | 
			
		||||
#        This may be useful on devices with RIL version >= 15 if auto
 | 
			
		||||
#        method fails
 | 
			
		||||
#   auto = Choose ss or ds based on the RIL version
 | 
			
		||||
#   none = Disable device state management
 | 
			
		||||
#
 | 
			
		||||
# Default auto
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user