/**
* @file datapipe.c
* This file implements the sinmple datapipe framework;
* this can be used to filter data and to setup data triggers
*
* Copyright (c) 2007 - 2008 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (c) 2014 - 2021 Jolla Ltd.
* Copyright (c) 2019 - 2020 Open Mobile Platform LLC.
*
* @author David Weinehall
* @author Simo Piiroinen
*
* mce is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* mce 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mce. If not, see .
*/
#include "mce.h"
#include "mce-log.h"
#include "mce-lib.h"
#include "evdev.h"
#include
#include
#include
/* ========================================================================= *
* Macros
* ========================================================================= */
#define cat2(a,b) a##b
#define cat3(a,b,c) a##b##c
#define datapipe_log(PIPE_, FMT_, ARGS_...)\
do {\
if( mce_log_p(LL_DEBUG) || \
mce_log_p_(LL_DEBUG,__FILE__,PIPE_->dp_name) ) {\
mce_log_unconditional(LL_DEBUG, __FILE__, __func__,\
FMT_ , ## ARGS_);\
}\
} while(0)
/* ========================================================================= *
* Types
* ========================================================================= */
struct datapipe_t
{
const char *dp_name; /**< Name of the datapipe */
GSList *dp_filters; /**< The filters */
GSList *dp_input_triggers; /**< Triggers called on indata */
GSList *dp_output_triggers; /**< Triggers called on outdata */
gconstpointer dp_cached_data; /**< Latest cached data */
gsize dp_datasize; /**< Size of data; NULL == automagic */
datapipe_filtering_t dp_read_only; /**< Datapipe is read only */
datapipe_cache_t dp_cache;
guint dp_gc_id;
guint dp_token;
const char *(*dp_value_repr_cb)(gconstpointer value);
const char *(*dp_change_repr_cb)(gconstpointer prev, gconstpointer curr);
};
#define DATAPIPE_INIT(NAME_,TYPE_,VALUE_,SIZE_,FILTERING_,CACHING_)\
{\
.dp_name = #NAME_ "_pipe",\
.dp_filters = 0,\
.dp_input_triggers = 0,\
.dp_output_triggers = 0,\
.dp_cached_data = GINT_TO_POINTER(VALUE_),\
.dp_datasize = SIZE_,\
.dp_read_only = FILTERING_,\
.dp_cache = CACHING_,\
.dp_gc_id = 0,\
.dp_token = 0,\
.dp_value_repr_cb = cat3(datapipe_hook_,TYPE_,_value),\
.dp_change_repr_cb = cat3(datapipe_hook_,TYPE_,_change),\
}
/* ========================================================================= *
* Prototypes
* ========================================================================= */
/* ------------------------------------------------------------------------- *
* DATAPIPE_HOOK
* ------------------------------------------------------------------------- */
static const char *datapipe_hook_int_value (gconstpointer data);
static const char *datapipe_hook_boolean_value (gconstpointer data);
static const char *datapipe_hook_string_value (gconstpointer data);
static const char *datapipe_hook_impulse_value (gconstpointer data);
static const char *datapipe_hook_input_event_value (gconstpointer data);
static const char *datapipe_hook_input_event_ptr_value (gconstpointer data);
static const char *datapipe_hook_display_state_value (gconstpointer data);
static const char *datapipe_hook_uiexception_type_value (gconstpointer data);
static const char *datapipe_hook_lockkey_state_value (gconstpointer data);
static const char *datapipe_hook_tristate_value (gconstpointer data);
static const char *datapipe_hook_cover_state_value (gconstpointer data);
static const char *datapipe_hook_orientation_state_value (gconstpointer data);
static const char *datapipe_hook_alarm_ui_state_value (gconstpointer data);
static const char *datapipe_hook_system_state_value (gconstpointer data);
static const char *datapipe_hook_submode_value (gconstpointer data);
static const char *datapipe_hook_submode_change (gconstpointer prev, gconstpointer curr);
static const char *datapipe_hook_call_state_value (gconstpointer data);
static const char *datapipe_hook_call_type_value (gconstpointer data);
static const char *datapipe_hook_tklock_request_value (gconstpointer data);
static const char *datapipe_hook_charger_state_value (gconstpointer data);
static const char *datapipe_hook_charger_type_value (gconstpointer data);
static const char *datapipe_hook_battery_status_value (gconstpointer data);
static const char *datapipe_hook_battery_state_value (gconstpointer data);
static const char *datapipe_hook_camera_button_state_value(gconstpointer data);
static const char *datapipe_hook_audio_route_value (gconstpointer data);
static const char *datapipe_hook_usb_cable_state_value (gconstpointer data);
static const char *datapipe_hook_thermal_state_value (gconstpointer data);
static const char *datapipe_hook_service_state_value (gconstpointer data);
static const char *datapipe_hook_devicelock_state_value (gconstpointer data);
static const char *datapipe_hook_fpstate_value (gconstpointer data);
static const char *datapipe_hook_memnotify_level_value (gconstpointer data);
/* ------------------------------------------------------------------------- *
* DATAPIPE
* ------------------------------------------------------------------------- */
const char *datapipe_name (const datapipe_t *self);
gconstpointer datapipe_value (const datapipe_t *self);
void datapipe_set_value (datapipe_t *self, gconstpointer data);
static void datapipe_gc (datapipe_t *self);
static gboolean datapipe_gc_cb (gpointer aptr);
static void datapipe_schedule_gc (datapipe_t *self);
static void datapipe_cancel_gc (datapipe_t *self);
gconstpointer datapipe_exec_full_real (datapipe_t *self, gconstpointer indata, const char *file, const char *func);
static void datapipe_add_filter (datapipe_t *self, gpointer (*filter)(gpointer data));
static void datapipe_remove_filter (datapipe_t *self, gpointer (*filter)(gpointer data));
static void datapipe_add_input_trigger (datapipe_t *self, void (*trigger)(gconstpointer data));
static void datapipe_remove_input_trigger (datapipe_t *self, void (*trigger)(gconstpointer data));
static void datapipe_add_output_trigger (datapipe_t *self, void (*trigger)(gconstpointer data));
static void datapipe_remove_output_trigger(datapipe_t *self, void (*trigger)(gconstpointer data));
static void datapipe_free (datapipe_t *self);
/* ------------------------------------------------------------------------- *
* MCE_DATAPIPE
* ------------------------------------------------------------------------- */
void mce_datapipe_init (void);
void mce_datapipe_quit (void);
static void mce_datapipe_install_handlers (datapipe_handler_t *bindings);
static void mce_datapipe_remove_handlers (datapipe_handler_t *bindings);
static void mce_datapipe_execute_handlers (datapipe_handler_t *bindings);
static gboolean mce_datapipe_execute_handlers_cb(gpointer aptr);
void mce_datapipe_init_bindings (datapipe_bindings_t *self);
void mce_datapipe_quit_bindings (datapipe_bindings_t *self);
void mce_datapipe_generate_activity (void);
void mce_datapipe_generate_inactivity(void);
/* ------------------------------------------------------------------------- *
* SUBMODE
* ------------------------------------------------------------------------- */
const char *submode_change_repr(submode_t prev, submode_t curr);
const char *submode_repr (submode_t submode);
/* ------------------------------------------------------------------------- *
* SYSTEM_STATE
* ------------------------------------------------------------------------- */
const char *system_state_repr(system_state_t state);
/* ------------------------------------------------------------------------- *
* DEVICELOCK_STATE
* ------------------------------------------------------------------------- */
const char *devicelock_state_repr(devicelock_state_t state);
/* ------------------------------------------------------------------------- *
* THERMAL_STATE
* ------------------------------------------------------------------------- */
const char *thermal_state_repr(thermal_state_t state);
/* ------------------------------------------------------------------------- *
* UIEXCEPTION_TYPE
* ------------------------------------------------------------------------- */
const char *uiexception_type_repr (uiexception_type_t type);
const char *uiexception_type_to_dbus(uiexception_type_t type);
/* ------------------------------------------------------------------------- *
* SERVICE_STATE
* ------------------------------------------------------------------------- */
const char *service_state_repr(service_state_t state);
/* ------------------------------------------------------------------------- *
* USB_CABLE_STATE
* ------------------------------------------------------------------------- */
const char *usb_cable_state_repr (usb_cable_state_t state);
const char *usb_cable_state_to_dbus(usb_cable_state_t state);
/* ------------------------------------------------------------------------- *
* CHARGER_TYPE
* ------------------------------------------------------------------------- */
const char *charger_type_repr (charger_type_t type);
const char *charger_type_to_dbus(charger_type_t type);
/* ------------------------------------------------------------------------- *
* CHARGER_STATE
* ------------------------------------------------------------------------- */
const char *charger_state_repr (charger_state_t state);
const char *charger_state_to_dbus(charger_state_t state);
/* ------------------------------------------------------------------------- *
* CAMERA_BUTTON_STATE
* ------------------------------------------------------------------------- */
const char *camera_button_state_repr(camera_button_state_t state);
/* ------------------------------------------------------------------------- *
* AUDIO_ROUTE
* ------------------------------------------------------------------------- */
const char *audio_route_repr(audio_route_t state);
/* ------------------------------------------------------------------------- *
* TKLOCK_REQUEST
* ------------------------------------------------------------------------- */
const char *tklock_request_repr(tklock_request_t state);
/* ------------------------------------------------------------------------- *
* TKLOCK_STATUS
* ------------------------------------------------------------------------- */
const char *tklock_status_repr(int status);
/* ------------------------------------------------------------------------- *
* BATTERY_STATUS
* ------------------------------------------------------------------------- */
const char *battery_status_repr (battery_status_t state);
const char *battery_status_to_dbus(battery_status_t state);
/* ------------------------------------------------------------------------- *
* BATTERY_STATE
* ------------------------------------------------------------------------- */
const char *battery_state_repr (battery_state_t state);
const char *battery_state_to_dbus(battery_state_t state);
/* ------------------------------------------------------------------------- *
* ALARM_STATE
* ------------------------------------------------------------------------- */
const char *alarm_state_repr(alarm_ui_state_t state);
/* ------------------------------------------------------------------------- *
* CALL_STATE
* ------------------------------------------------------------------------- */
const char *call_state_to_dbus (call_state_t state);
call_state_t call_state_from_dbus(const char *name);
const char *call_state_repr (call_state_t state);
/* ------------------------------------------------------------------------- *
* CALL_TYPE
* ------------------------------------------------------------------------- */
const char *call_type_repr (call_type_t type);
call_type_t call_type_parse(const char *name);
/* ------------------------------------------------------------------------- *
* COVER_STATE
* ------------------------------------------------------------------------- */
const char *cover_state_repr(cover_state_t state);
/* ------------------------------------------------------------------------- *
* PROXIMITY_STATE
* ------------------------------------------------------------------------- */
const char *proximity_state_repr(cover_state_t state);
/* ------------------------------------------------------------------------- *
* DISPLAY_STATE
* ------------------------------------------------------------------------- */
const char *display_state_repr(display_state_t state);
/* ------------------------------------------------------------------------- *
* ORIENTATION_STATE
* ------------------------------------------------------------------------- */
const char *orientation_state_repr(orientation_state_t state);
/* ------------------------------------------------------------------------- *
* KEY_STATE
* ------------------------------------------------------------------------- */
const char *key_state_repr(key_state_t state);
/* ------------------------------------------------------------------------- *
* TRISTATE
* ------------------------------------------------------------------------- */
const char *tristate_repr(tristate_t state);
/* ------------------------------------------------------------------------- *
* FPSTATE
* ------------------------------------------------------------------------- */
fpstate_t fpstate_parse(const char *name);
const char *fpstate_repr (fpstate_t state);
/* ========================================================================= *
* DATAPIPE_HOOK
* ========================================================================= */
/* For each datatype used in datapipes there exist:
* - datapipe_hook__value
* - datapipe_hook__changes
*
* These are used in expansion of #DATAPIPE_INIT() macro and must resolve
* either to a valid callback function or null pointer.
*/
static const char *
datapipe_hook_int_value(gconstpointer data)
{
static char buf[32];
snprintf(buf, sizeof buf, "%d", GPOINTER_TO_INT(data));
return buf;
}
#define datapipe_hook_int_change 0
static const char *
datapipe_hook_boolean_value(gconstpointer data)
{
return data ? "true" : "false";
}
#define datapipe_hook_boolean_change 0
static const char *
datapipe_hook_string_value(gconstpointer data)
{
return data;
}
#define datapipe_hook_string_change 0
static const char *
datapipe_hook_impulse_value(gconstpointer data)
{
(void)data;
return "impulse";
}
#define datapipe_hook_impulse_change 0
static const char *
datapipe_hook_input_event_value(gconstpointer data)
{
static char buf[64];
const struct input_event *ev = data;
if( !ev )
return "NULL event!";
snprintf(buf, sizeof buf, "type: %s, code: %s, value: %d",
evdev_get_event_type_name(ev->type),
evdev_get_event_code_name(ev->type, ev->code),
ev->value);
return buf;
}
#define datapipe_hook_input_event_change 0
static const char *
datapipe_hook_input_event_ptr_value(gconstpointer data)
{
const struct input_event *const*evp = data;
if( !evp )
return "NULL event ptr!";
return datapipe_hook_input_event_value(*evp);
}
#define datapipe_hook_input_event_ptr_change 0
static const char *
datapipe_hook_display_state_value(gconstpointer data)
{
display_state_t display_state = GPOINTER_TO_INT(data);
return display_state_repr(display_state);
}
#define datapipe_hook_display_state_change 0
static const char *
datapipe_hook_uiexception_type_value(gconstpointer data)
{
uiexception_type_t value = GPOINTER_TO_INT(data);
return uiexception_type_repr(value);
}
#define datapipe_hook_uiexception_type_change 0
static const char *
datapipe_hook_lockkey_state_value(gconstpointer data)
{
key_state_t key_state = GPOINTER_TO_INT(data);
return key_state_repr(key_state);
}
#define datapipe_hook_lockkey_state_change 0
static const char *
datapipe_hook_tristate_value(gconstpointer data)
{
tristate_t value = GPOINTER_TO_INT(data);
return tristate_repr(value);
}
#define datapipe_hook_tristate_change 0
static const char *
datapipe_hook_cover_state_value(gconstpointer data)
{
cover_state_t value = GPOINTER_TO_INT(data);
return cover_state_repr(value);
}
#define datapipe_hook_cover_state_change 0
static const char *
datapipe_hook_orientation_state_value(gconstpointer data)
{
orientation_state_t value = GPOINTER_TO_INT(data);
return orientation_state_repr(value);
}
#define datapipe_hook_orientation_state_change 0
static const char *
datapipe_hook_alarm_ui_state_value(gconstpointer data)
{
alarm_ui_state_t value = GPOINTER_TO_INT(data);
return alarm_state_repr(value);
}
#define datapipe_hook_alarm_ui_state_change 0
static const char *
datapipe_hook_system_state_value(gconstpointer data)
{
system_state_t value = GPOINTER_TO_INT(data);
return system_state_repr(value);
}
#define datapipe_hook_system_state_change 0
static const char *
datapipe_hook_submode_value(gconstpointer data)
{
submode_t value = GPOINTER_TO_INT(data);
return submode_repr(value);
}
static const char *
datapipe_hook_submode_change(gconstpointer prev, gconstpointer curr)
{
submode_t v1 = GPOINTER_TO_INT(prev);
submode_t v2 = GPOINTER_TO_INT(curr);
return submode_change_repr(v1, v2);
}
static const char *
datapipe_hook_call_state_value(gconstpointer data)
{
call_state_t value = GPOINTER_TO_INT(data);
return call_state_repr(value);
}
#define datapipe_hook_call_state_change 0
static const char *
datapipe_hook_call_type_value(gconstpointer data)
{
call_type_t value = GPOINTER_TO_INT(data);
return call_type_repr(value);
}
#define datapipe_hook_call_type_change 0
static const char *
datapipe_hook_tklock_request_value(gconstpointer data)
{
tklock_request_t value = GPOINTER_TO_INT(data);
return tklock_request_repr(value);
}
#define datapipe_hook_tklock_request_change 0
static const char *
datapipe_hook_charger_type_value(gconstpointer data)
{
charger_type_t value = GPOINTER_TO_INT(data);
return charger_type_repr(value);
}
#define datapipe_hook_charger_type_change 0
static const char *
datapipe_hook_charger_state_value(gconstpointer data)
{
charger_state_t value = GPOINTER_TO_INT(data);
return charger_state_repr(value);
}
#define datapipe_hook_charger_state_change 0
static const char *
datapipe_hook_battery_status_value(gconstpointer data)
{
battery_status_t value = GPOINTER_TO_INT(data);
return battery_status_repr(value);
}
#define datapipe_hook_battery_status_change 0
static const char *
datapipe_hook_battery_state_value(gconstpointer data)
{
battery_state_t value = GPOINTER_TO_INT(data);
return battery_state_repr(value);
}
#define datapipe_hook_battery_state_change 0
static const char *
datapipe_hook_camera_button_state_value(gconstpointer data)
{
camera_button_state_t value = GPOINTER_TO_INT(data);
return camera_button_state_repr(value);
}
#define datapipe_hook_camera_button_state_change 0
static const char *
datapipe_hook_audio_route_value(gconstpointer data)
{
audio_route_t value = GPOINTER_TO_INT(data);
return audio_route_repr(value);
}
#define datapipe_hook_audio_route_change 0
static const char *
datapipe_hook_usb_cable_state_value(gconstpointer data)
{
usb_cable_state_t value = GPOINTER_TO_INT(data);
return usb_cable_state_repr(value);
}
#define datapipe_hook_usb_cable_state_change 0
static const char *
datapipe_hook_thermal_state_value(gconstpointer data)
{
thermal_state_t value = GPOINTER_TO_INT(data);
return thermal_state_repr(value);
}
#define datapipe_hook_thermal_state_change 0
static const char *
datapipe_hook_service_state_value(gconstpointer data)
{
service_state_t value = GPOINTER_TO_INT(data);
return service_state_repr(value);
}
#define datapipe_hook_service_state_change 0
static const char *
datapipe_hook_devicelock_state_value(gconstpointer data)
{
devicelock_state_t value = GPOINTER_TO_INT(data);
return devicelock_state_repr(value);
}
#define datapipe_hook_devicelock_state_change 0
static const char *
datapipe_hook_fpstate_value(gconstpointer data)
{
fpstate_t value = GPOINTER_TO_INT(data);
return fpstate_repr(value);
}
#define datapipe_hook_fpstate_change 0
static const char *
datapipe_hook_memnotify_level_value(gconstpointer data)
{
memnotify_level_t value = GPOINTER_TO_INT(data);
return memnotify_level_repr(value);
}
#define datapipe_hook_memnotify_level_change 0
/* ========================================================================= *
* Data
* ========================================================================= */
/* Available datapipes */
/** LED brightness */
datapipe_t led_brightness_pipe = DATAPIPE_INIT(led_brightness, int, 0, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_INDATA);
/** LPM brightness */
datapipe_t lpm_brightness_pipe = DATAPIPE_INIT(lpm_brightness, int, 0, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_INDATA);
/** State of device; read only */
datapipe_t device_inactive_pipe = DATAPIPE_INIT(device_inactive, boolean, true, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Device inactivity events; read only */
datapipe_t inactivity_event_pipe = DATAPIPE_INIT(inactivity_event, boolean, true, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** LED pattern to activate; read only */
datapipe_t led_pattern_activate_pipe = DATAPIPE_INIT(led_pattern_activate, string, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** LED pattern to deactivate; read only */
datapipe_t led_pattern_deactivate_pipe = DATAPIPE_INIT(led_pattern_deactivate, string, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** resumed from suspend notification; read only */
datapipe_t resume_detected_event_pipe = DATAPIPE_INIT(resume_detected_event, impulse, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** Non-synthetized user activity; read only */
datapipe_t user_activity_event_pipe = DATAPIPE_INIT(user_activity_event, input_event, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** State of display; read only */
datapipe_t display_state_curr_pipe = DATAPIPE_INIT(display_state_curr, display_state, MCE_DISPLAY_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Desired state of display; write only */
datapipe_t display_state_request_pipe = DATAPIPE_INIT(display_state_request, display_state, MCE_DISPLAY_UNDEF, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_DEFAULT);
/** Next (non-transitional) state of display; read only */
datapipe_t display_state_next_pipe = DATAPIPE_INIT(display_state_next, display_state, MCE_DISPLAY_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** exceptional ui state; read write */
datapipe_t uiexception_type_pipe = DATAPIPE_INIT(uiexception_type, uiexception_type, UIEXCEPTION_TYPE_NONE, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/**
* Display brightness;
* bits 0-7 is brightness in percent (0-100)
* upper 8 bits is high brightness boost (0-2)
*/
datapipe_t display_brightness_pipe = DATAPIPE_INIT(display_brightness, int, 3, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_INDATA);
/** Key backlight */
datapipe_t key_backlight_brightness_pipe = DATAPIPE_INIT(key_backlight_brightness, int, 0, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_INDATA);
/** A key has been pressed */
datapipe_t keypress_event_pipe = DATAPIPE_INIT(keypress_event, input_event_ptr, 0, sizeof (struct input_event), DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** Touchscreen activity took place */
datapipe_t touchscreen_event_pipe = DATAPIPE_INIT(touchscreen_event, input_event_ptr, 0, sizeof (struct input_event), DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** The lock-key has been pressed; read only */
datapipe_t lockkey_state_pipe = DATAPIPE_INIT(lockkey_state, lockkey_state, KEY_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The init-done condition has been reached; read only */
datapipe_t init_done_pipe = DATAPIPE_INIT(init_done, tristate, TRISTATE_UNKNOWN, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Keyboard open/closed; read only */
datapipe_t keyboard_slide_state_pipe = DATAPIPE_INIT(keyboard_slide_state, cover_state, COVER_CLOSED, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Keyboard available; read only */
datapipe_t keyboard_available_state_pipe = DATAPIPE_INIT(keyboard_available_state, cover_state, COVER_CLOSED, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Mouse available; read only */
datapipe_t mouse_available_state_pipe = DATAPIPE_INIT(mouse_available_state, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Lid sensor is working state; read/write */
datapipe_t lid_sensor_is_working_pipe = DATAPIPE_INIT(lid_sensor_is_working, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Lid cover sensor open/closed; read only */
datapipe_t lid_sensor_actual_pipe = DATAPIPE_INIT(lid_sensor_actual, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Lid cover policy state; read only */
datapipe_t lid_sensor_filtered_pipe = DATAPIPE_INIT(lid_sensor_filtered, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Lens cover open/closed; read only */
datapipe_t lens_cover_state_pipe = DATAPIPE_INIT(lens_cover_state, cover_state, COVER_CLOSED, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Proximity sensor; read only */
datapipe_t proximity_sensor_actual_pipe = DATAPIPE_INIT(proximity_sensor_actual, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Proximity sensor; read only */
datapipe_t proximity_sensor_effective_pipe = DATAPIPE_INIT(proximity_sensor_effective, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Proximity sensor on-demand control; write only
*
* The data fed into proximity_sensor_required_pipe needs to
* be a statically allocated const string with format like:
*
* ""
*
* Where is one of:
*
* - PROXIMITY_SENSOR_REQUIRED_ADD: is added to the
* list of resons to keep on-demand proximity sensor mode
* active.
*
* - PROXIMITY_SENSOR_REQUIRED_REM: is from the the
* list of resons to keep on-demand proximity sensor mode
* active.
*/
datapipe_t proximity_sensor_required_pipe = DATAPIPE_INIT(proximity_sensor_required, string, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** proximity blanking; read only */
datapipe_t proximity_blanked_pipe = DATAPIPE_INIT(proximity_blanked, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Ambient light sensor; read only */
datapipe_t light_sensor_actual_pipe = DATAPIPE_INIT(light_sensor_actual, int, 400, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Filtered ambient light level; read only */
datapipe_t light_sensor_filtered_pipe = DATAPIPE_INIT(light_sensor_filtered, int, 400, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Temporary ambient light sensor enable; read/write */
datapipe_t light_sensor_poll_request_pipe = DATAPIPE_INIT(light_sensor_poll_request, boolean, false, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_DEFAULT);
/** Orientation sensor; read only */
datapipe_t orientation_sensor_actual_pipe = DATAPIPE_INIT(orientation_sensor_actual, orientation_state, MCE_ORIENTATION_UNDEFINED, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The alarm UI state */
datapipe_t alarm_ui_state_pipe = DATAPIPE_INIT(alarm_ui_state, alarm_ui_state, MCE_ALARM_UI_INVALID_INT32, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The device state; read only */
datapipe_t system_state_pipe = DATAPIPE_INIT(system_state, system_state, MCE_SYSTEM_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Enable/disable radios */
datapipe_t master_radio_enabled_pipe = DATAPIPE_INIT(master_radio_enabled, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The device submode */
datapipe_t submode_pipe = DATAPIPE_INIT(submode, submode, MCE_SUBMODE_NORMAL, 0, DATAPIPE_FILTERING_ALLOWED, DATAPIPE_CACHE_DEFAULT);
/** The call state */
datapipe_t call_state_pipe = DATAPIPE_INIT(call_state, call_state, CALL_STATE_NONE, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The ignore incoming call "state".
*
* Note: Related actions happen when true is executed on the
* datapipe, but the cached value always remains at false.
*/
datapipe_t ignore_incoming_call_event_pipe = DATAPIPE_INIT(ignore_incoming_call_event, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** The call type */
datapipe_t call_type_pipe = DATAPIPE_INIT(call_type, call_type, CALL_TYPE_NORMAL, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The touchscreen/keypad lock state */
datapipe_t tklock_request_pipe = DATAPIPE_INIT(tklock_request, tklock_request, TKLOCK_REQUEST_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** UI side is in a state where user interaction is expected */
datapipe_t interaction_expected_pipe = DATAPIPE_INIT(interaction_expected, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Charger type; read only */
datapipe_t charger_type_pipe = DATAPIPE_INIT(charger_type, charger_type, CHARGER_TYPE_NONE, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Charger state; read only */
datapipe_t charger_state_pipe = DATAPIPE_INIT(charger_state, charger_state, CHARGER_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Battery status; read only */
datapipe_t battery_status_pipe = DATAPIPE_INIT(battery_status, battery_status, BATTERY_STATUS_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Battery state; read only */
datapipe_t battery_state_pipe = DATAPIPE_INIT(battery_state, battery_state, BATTERY_STATE_UNKNOWN, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Battery charge level; read only */
datapipe_t battery_level_pipe = DATAPIPE_INIT(battery_level, int, MCE_BATTERY_LEVEL_UNKNOWN, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Topmost window PID; read only */
datapipe_t topmost_window_pid_pipe = DATAPIPE_INIT(topmost_window_pid, int, -1, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Camera button; read only */
datapipe_t camera_button_state_pipe = DATAPIPE_INIT(camera_button_state, camera_button_state, CAMERA_BUTTON_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** The inactivity timeout; read only */
datapipe_t inactivity_delay_pipe = DATAPIPE_INIT(inactivity_delay, int, DEFAULT_INACTIVITY_DELAY, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Audio routing state; read only */
datapipe_t audio_route_pipe = DATAPIPE_INIT(audio_route, audio_route, AUDIO_ROUTE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** USB cable has been connected/disconnected; read only */
datapipe_t usb_cable_state_pipe = DATAPIPE_INIT(usb_cable_state, usb_cable_state, USB_CABLE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** A jack connector has been connected/disconnected; read only */
datapipe_t jack_sense_state_pipe = DATAPIPE_INIT(jack_sense_state, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Power save mode is active; read only */
datapipe_t power_saving_mode_active_pipe = DATAPIPE_INIT(power_saving_mode_active, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Thermal state; read only */
datapipe_t thermal_state_pipe = DATAPIPE_INIT(thermal_state, thermal_state, THERMAL_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Heartbeat; read only */
datapipe_t heartbeat_event_pipe = DATAPIPE_INIT(heartbeat_event, impulse, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** compositor availability; read only */
datapipe_t compositor_service_state_pipe = DATAPIPE_INIT(compositor_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** lipstick availability; read only */
datapipe_t lipstick_service_state_pipe = DATAPIPE_INIT(lipstick_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** devicelock availability; read only */
datapipe_t devicelock_service_state_pipe = DATAPIPE_INIT(devicelock_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** usbmoded availability; read only */
datapipe_t usbmoded_service_state_pipe = DATAPIPE_INIT(usbmoded_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** ngfd availability; read only */
datapipe_t ngfd_service_state_pipe = DATAPIPE_INIT(ngfd_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Request ngfd event playing */
datapipe_t ngfd_event_request_pipe = DATAPIPE_INIT(ngfd_event_request, string, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING);
/** dsme availability; read only */
datapipe_t dsme_service_state_pipe = DATAPIPE_INIT(dsme_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** thermalmanager availability; read only */
datapipe_t thermalmanager_service_state_pipe = DATAPIPE_INIT(thermalmanager_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** bluez availability; read only */
datapipe_t bluez_service_state_pipe = DATAPIPE_INIT(bluez_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** PackageKit Locked status; read only */
datapipe_t packagekit_locked_pipe = DATAPIPE_INIT(packagekit_locked, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Update mode active status; read only */
datapipe_t osupdate_running_pipe = DATAPIPE_INIT(osupdate_running, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Shutting down; read only */
datapipe_t shutting_down_pipe = DATAPIPE_INIT(shutting_down, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Device Lock state; read only */
datapipe_t devicelock_state_pipe = DATAPIPE_INIT(devicelock_state, devicelock_state, DEVICELOCK_STATE_UNDEFINED, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** touchscreen input detected; read only */
datapipe_t touch_detected_pipe = DATAPIPE_INIT(touch_detected, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** touchscreen input grab required; read/write */
datapipe_t touch_grab_wanted_pipe = DATAPIPE_INIT(touch_grab_wanted, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** touchscreen input grab active; read only */
datapipe_t touch_grab_active_pipe = DATAPIPE_INIT(touch_grab_active, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** keypad input grab required; read/write */
datapipe_t keypad_grab_wanted_pipe = DATAPIPE_INIT(keypad_grab_wanted, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** keypad input grab active; read only */
datapipe_t keypad_grab_active_pipe = DATAPIPE_INIT(keypad_grab_active, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** music playback active; read only */
datapipe_t music_playback_ongoing_pipe = DATAPIPE_INIT(music_playback_ongoing, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** fingerprint daemon availability; read only */
datapipe_t fpd_service_state_pipe = DATAPIPE_INIT(fpd_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** fingerprint daemon state; read only */
datapipe_t fpstate_pipe = DATAPIPE_INIT(fpstate, fpstate, FPSTATE_UNSET, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** fingerprint is enrolling; read only */
datapipe_t enroll_in_progress_pipe = DATAPIPE_INIT(enroll_in_progress, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/** Memory pressure level; read only */
datapipe_t memnotify_level_pipe = DATAPIPE_INIT(memnotify_level, memnotify_level, MEMNOTIFY_LEVEL_UNKNOWN, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);
/* ========================================================================= *
* Functions
* ========================================================================= */
/** Get name of datapipe
*
* @param self The datapipe, or NULL
*
* @return datapipe name, or suitable placeholder value
*/
const char *
datapipe_name(const datapipe_t *self)
{
const char *name = "invalid";
if( self )
name = self->dp_name ?: "unnamed";
return name;
}
/** Get value of datapipe
*
* @param self The datapipe
*
* @return datapipe value, as void pointer
*/
gconstpointer
datapipe_value(const datapipe_t *self)
{
return self->dp_cached_data;
}
/** Set value of datapipe
*
* Note: Do not call this function from outside datapipe.c.
*
* While such calls exist to facilitate legacy hacks in the
* display plugin - no new code like that should be added.
*
* FIXME: Remove offending call sites and make this function
* static.
*
* The proper way to modify datapipe content is to use
* #datapipe_exec_full() function.
*
* @param self The datapipe
* @paran data The value, as void pointer
*/
void
datapipe_set_value(datapipe_t *self, gconstpointer data)
{
gconstpointer prev = self->dp_cached_data;
self->dp_cached_data = data;
if( prev != data ) {
if( self->dp_change_repr_cb ) {
datapipe_log(self, "%s: %s",
datapipe_name(self),
self->dp_change_repr_cb(prev, data));
}
else if( self->dp_value_repr_cb ) {
gchar *saved = g_strdup(self->dp_value_repr_cb(prev));
datapipe_log(self, "%s: %s -> %s",
datapipe_name(self),
saved,
self->dp_value_repr_cb(data));
g_free(saved);
}
else {
datapipe_log(self, "%s: %p -> %p",
datapipe_name(self),
prev, data);
}
}
}
/** Garbage collect stale callback slots
*
* While it can be assumed to be extremely rare, filters and triggers can end
* up being added/removed due to datapipe activity. In order to allow O(N)
* traversal in datapipe_exec_full() slots with removed callbacks are
* zeroed and left behind to be collected from idle callback.
*
* @param self The datapipe
*/
static void
datapipe_gc(datapipe_t *self)
{
/* Cancel pending idle callback */
datapipe_cancel_gc(self);
/* Flush out slots with null callback */
self->dp_input_triggers = g_slist_remove_all(self->dp_input_triggers, 0);
self->dp_filters = g_slist_remove_all(self->dp_filters, 0);
self->dp_output_triggers = g_slist_remove_all(self->dp_output_triggers, 0);
}
/** Garbage collect idle callback
*
* @param self The datapipe, as void pointer
*
* @return G_SOURCE_REMOVE
*/
static gboolean
datapipe_gc_cb(gpointer aptr)
{
datapipe_t *self = aptr;
self->dp_gc_id = 0;
datapipe_gc(self);
return G_SOURCE_REMOVE;
}
/** Schedule garbage collection
*
* @param self The datapipe, as void pointer
*/
static void
datapipe_schedule_gc(datapipe_t *self)
{
if( !self->dp_gc_id ) {
self->dp_gc_id = g_idle_add(datapipe_gc_cb, self);
}
}
/** Cancel garbage collection
*
* @param self The datapipe, as void pointer
*/
static void
datapipe_cancel_gc(datapipe_t *self)
{
if( self->dp_gc_id ) {
g_source_remove(self->dp_gc_id),
self->dp_gc_id = 0;
}
}
/** Execute the datapipe
*
* Note: Use #datapipe_exec_full() macro instead of calling
* this function directly.
*
* @param self The datapipe to execute
* @param indata The input data to run through the datapipe
* @return The processed data
*/
gconstpointer
datapipe_exec_full_real(datapipe_t *self, gconstpointer indata,
const char *file, const char *func)
{
gconstpointer outdata = NULL;
if (self == NULL) {
mce_log(LL_ERR,
"datapipe_exec_full_real() called "
"without a valid datapipe");
goto EXIT;
}
if( mce_log_p(LL_DEBUG) ||
mce_log_p_(LL_DEBUG, file, func) ||
mce_log_p_(LL_DEBUG, __FILE__, datapipe_name(self)) ) {
if( self->dp_value_repr_cb ) {
mce_log_unconditional(LL_DEBUG, file, func, "%s: execute %s",
datapipe_name(self),
self->dp_value_repr_cb(indata));
}
else {
mce_log_unconditional(LL_DEBUG, file, func, "%s: execute %p",
datapipe_name(self), indata);
}
}
guint token = ++self->dp_token;
datapipe_cache_t cache_indata = self->dp_cache;
/* Optionally cache the value at the input stage */
if( cache_indata & (DATAPIPE_CACHE_INDATA | DATAPIPE_CACHE_OUTDATA) ) {
datapipe_set_value(self, indata);
}
/* Execute input value callbacks */
for( GSList *item = self->dp_input_triggers; item; item = item->next ) {
void (*trigger)(gconstpointer input) = item->data;
if( !trigger )
continue;
if( self->dp_token != token ) {
mce_log(LL_WARN, "%s: recursion detected at input triggers",
datapipe_name(self));
goto EXIT;
}
trigger(indata);
}
/* Determine output value */
outdata = indata;
if( self->dp_read_only == DATAPIPE_FILTERING_ALLOWED ) {
for( GSList *item = self->dp_filters; item; item = item->next ) {
gconstpointer (*filter)(gconstpointer input) = item->data;
if( !filter )
continue;
if( self->dp_token != token ) {
mce_log(LL_WARN, "%s: recursion detected at input filters",
datapipe_name(self));
goto EXIT;
}
outdata = filter(outdata);
}
}
/* Optionally cache the value at the output stage */
if( cache_indata & DATAPIPE_CACHE_OUTDATA ) {
datapipe_set_value(self, outdata);
}
/* Execute output value callbacks */
for( GSList *item = self->dp_output_triggers; item; item = item->next ) {
void (*trigger)(gconstpointer input) = item->data;
if( !trigger )
continue;
if( self->dp_token != token ) {
mce_log(LL_WARN, "%s: recursion detected at output triggers",
datapipe_name(self));
goto EXIT;
}
trigger(outdata);
}
EXIT:
return outdata;
}
/**
* Append a filter to an existing datapipe
*
* @param self The datapipe to manipulate
* @param filter The filter to add to the datapipe
*/
static void
datapipe_add_filter(datapipe_t *self,
gpointer (*filter)(gpointer data))
{
if (self == NULL) {
mce_log(LL_ERR, "called with NULL datapipe");
goto EXIT;
}
if (filter == NULL) {
mce_log(LL_ERR, "called with NULL filter");
goto EXIT;
}
if (self->dp_read_only == DATAPIPE_FILTERING_DENIED) {
mce_log(LL_ERR, "called on read only datapipe");
goto EXIT;
}
self->dp_filters = g_slist_append(self->dp_filters, filter);
EXIT:
return;
}
/**
* Remove a filter from an existing datapipe
* Non-existing filters are ignored
*
* @param self The datapipe to manipulate
* @param filter The filter to remove from the datapipe
*/
static void
datapipe_remove_filter(datapipe_t *self,
gpointer (*filter)(gpointer data))
{
if (self == NULL) {
mce_log(LL_ERR, "called with NULL datapipe");
goto EXIT;
}
if (filter == NULL) {
mce_log(LL_ERR, "called with NULL filter");
goto EXIT;
}
if (self->dp_read_only == DATAPIPE_FILTERING_DENIED) {
mce_log(LL_ERR, "called on read only datapipe");
goto EXIT;
}
GSList *itm = g_slist_find(self->dp_filters, filter);
if( !itm )
mce_log(LL_DEBUG, "called with non-existing filter");
else
itm->data = 0, datapipe_schedule_gc(self);
EXIT:
return;
}
/**
* Append an input trigger to an existing datapipe
*
* @param self The datapipe to manipulate
* @param trigger The trigger to add to the datapipe
*/
static void
datapipe_add_input_trigger(datapipe_t *self,
void (*trigger)(gconstpointer data))
{
if (self == NULL) {
mce_log(LL_ERR, "called with NULL datapipe");
goto EXIT;
}
if (trigger == NULL) {
mce_log(LL_ERR, "called with NULL trigger");
goto EXIT;
}
self->dp_input_triggers = g_slist_append(self->dp_input_triggers,
trigger);
EXIT:
return;
}
/**
* Remove an input trigger from an existing datapipe
* Non-existing triggers are ignored
*
* @param self The datapipe to manipulate
* @param trigger The trigger to remove from the datapipe
*/
static void
datapipe_remove_input_trigger(datapipe_t *self,
void (*trigger)(gconstpointer data))
{
if (self == NULL) {
mce_log(LL_ERR, "called with NULL datapipe");
goto EXIT;
}
if (trigger == NULL) {
mce_log(LL_ERR, "called with NULL trigger");
goto EXIT;
}
GSList *itm = g_slist_find(self->dp_input_triggers, trigger);
if( !itm )
mce_log(LL_DEBUG, "called with non-existing trigger");
else
itm->data = 0, datapipe_schedule_gc(self);
EXIT:
return;
}
/**
* Append an output trigger to an existing datapipe
*
* @param self The datapipe to manipulate
* @param trigger The trigger to add to the datapipe
*/
static void
datapipe_add_output_trigger(datapipe_t *self,
void (*trigger)(gconstpointer data))
{
if (self == NULL) {
mce_log(LL_ERR, "called with NULL datapipe");
goto EXIT;
}
if (trigger == NULL) {
mce_log(LL_ERR, "called with NULL trigger");
goto EXIT;
}
self->dp_output_triggers = g_slist_append(self->dp_output_triggers,
trigger);
EXIT:
return;
}
/**
* Remove an output trigger from an existing datapipe
* Non-existing triggers are ignored
*
* @param self The datapipe to manipulate
* @param trigger The trigger to remove from the datapipe
*/
static void
datapipe_remove_output_trigger(datapipe_t *self,
void (*trigger)(gconstpointer data))
{
if (self == NULL) {
mce_log(LL_ERR, "called with NULL datapipe");
goto EXIT;
}
if (trigger == NULL) {
mce_log(LL_ERR, "called with NULL trigger");
goto EXIT;
}
GSList *itm = g_slist_find(self->dp_output_triggers, trigger);
if( !itm )
mce_log(LL_DEBUG, "called with non-existing trigger");
else
itm->data = 0, datapipe_schedule_gc(self);
EXIT:
return;
}
/**
* Deinitialize a datapipe
*
* @param self The datapipe to manipulate
*/
static void
datapipe_free(datapipe_t *self)
{
if (self == NULL) {
mce_log(LL_ERR,
"datapipe_free() called "
"without a valid datapipe");
goto EXIT;
}
datapipe_gc(self);
/* Warn about still registered filters/triggers */
if (self->dp_filters != NULL) {
mce_log(LL_INFO,
"datapipe_free() called on a datapipe that "
"still has registered filter(s)");
}
if (self->dp_input_triggers != NULL) {
mce_log(LL_INFO,
"datapipe_free() called on a datapipe that "
"still has registered input_trigger(s)");
}
if (self->dp_output_triggers != NULL) {
mce_log(LL_INFO,
"datapipe_free() called on a datapipe that "
"still has registered output_trigger(s)");
}
EXIT:
return;
}
/** Setup all datapipes
*/
void mce_datapipe_init(void)
{
/* Currently all datapipes are initialized statically
* and this function exists for the sake of symmetry.
*/
}
/** Free all datapipes
*/
void mce_datapipe_quit(void)
{
datapipe_free(&thermal_state_pipe);
datapipe_free(&power_saving_mode_active_pipe);
datapipe_free(&jack_sense_state_pipe);
datapipe_free(&usb_cable_state_pipe);
datapipe_free(&audio_route_pipe);
datapipe_free(&inactivity_delay_pipe);
datapipe_free(&battery_level_pipe);
datapipe_free(&topmost_window_pid_pipe);
datapipe_free(&camera_button_state_pipe);
datapipe_free(&battery_status_pipe);
datapipe_free(&battery_state_pipe);
datapipe_free(&charger_type_pipe);
datapipe_free(&charger_state_pipe);
datapipe_free(&interaction_expected_pipe);
datapipe_free(&tklock_request_pipe);
datapipe_free(&proximity_sensor_actual_pipe);
datapipe_free(&proximity_sensor_effective_pipe);
datapipe_free(&proximity_sensor_required_pipe);
datapipe_free(&proximity_blanked_pipe);
datapipe_free(&light_sensor_actual_pipe);
datapipe_free(&light_sensor_filtered_pipe);
datapipe_free(&light_sensor_poll_request_pipe);
datapipe_free(&orientation_sensor_actual_pipe);
datapipe_free(&lens_cover_state_pipe);
datapipe_free(&lid_sensor_is_working_pipe);
datapipe_free(&lid_sensor_actual_pipe);
datapipe_free(&lid_sensor_filtered_pipe);
datapipe_free(&keyboard_slide_state_pipe);
datapipe_free(&keyboard_available_state_pipe);
datapipe_free(&mouse_available_state_pipe);
datapipe_free(&lockkey_state_pipe);
datapipe_free(&init_done_pipe);
datapipe_free(&device_inactive_pipe);
datapipe_free(&inactivity_event_pipe);
datapipe_free(&touchscreen_event_pipe);
datapipe_free(&keypress_event_pipe);
datapipe_free(&key_backlight_brightness_pipe);
datapipe_free(&user_activity_event_pipe);
datapipe_free(&led_pattern_deactivate_pipe);
datapipe_free(&led_pattern_activate_pipe);
datapipe_free(&resume_detected_event_pipe);
datapipe_free(&led_brightness_pipe);
datapipe_free(&lpm_brightness_pipe);
datapipe_free(&display_brightness_pipe);
datapipe_free(&display_state_curr_pipe);
datapipe_free(&display_state_request_pipe);
datapipe_free(&display_state_next_pipe);
datapipe_free(&uiexception_type_pipe);
datapipe_free(&submode_pipe);
datapipe_free(&alarm_ui_state_pipe);
datapipe_free(&call_type_pipe);
datapipe_free(&call_state_pipe);
datapipe_free(&ignore_incoming_call_event_pipe);
datapipe_free(&master_radio_enabled_pipe);
datapipe_free(&system_state_pipe);
datapipe_free(&heartbeat_event_pipe);
datapipe_free(&compositor_service_state_pipe);
datapipe_free(&lipstick_service_state_pipe);
datapipe_free(&devicelock_service_state_pipe);
datapipe_free(&usbmoded_service_state_pipe);
datapipe_free(&ngfd_service_state_pipe);
datapipe_free(&ngfd_event_request_pipe);
datapipe_free(&dsme_service_state_pipe);
datapipe_free(&thermalmanager_service_state_pipe);
datapipe_free(&bluez_service_state_pipe);
datapipe_free(&packagekit_locked_pipe);
datapipe_free(&osupdate_running_pipe);
datapipe_free(&shutting_down_pipe);
datapipe_free(&devicelock_state_pipe);
datapipe_free(&touch_grab_active_pipe);
datapipe_free(&touch_grab_wanted_pipe);
datapipe_free(&touch_detected_pipe);
datapipe_free(&keypad_grab_active_pipe);
datapipe_free(&keypad_grab_wanted_pipe);
datapipe_free(&music_playback_ongoing_pipe);
datapipe_free(&fpd_service_state_pipe);
datapipe_free(&fpstate_pipe);
datapipe_free(&enroll_in_progress_pipe);
datapipe_free(&memnotify_level_pipe);
}
/** Convert submode_t bitmap changes to human readable string
*
* @param prev submode_t bitmap changed from
* @param curr submode_t bitmap changed to
*
* @return human readable representation of submode
*/
const char *submode_change_repr(submode_t prev, submode_t curr)
{
static const struct {
submode_t bit; const char *name;
} lut[] = {
{ MCE_SUBMODE_INVALID, "INVALID" },
{ MCE_SUBMODE_TKLOCK, "TKLOCK" },
{ MCE_SUBMODE_EVEATER, "EVEATER" },
{ MCE_SUBMODE_BOOTUP, "BOOTUP" },
{ MCE_SUBMODE_TRANSITION, "TRANSITION" },
{ MCE_SUBMODE_AUTORELOCK, "AUTORELOCK" },
{ MCE_SUBMODE_VISUAL_TKLOCK, "VISUAL_TKLOCK" },
{ MCE_SUBMODE_POCKET, "POCKET" },
{ MCE_SUBMODE_PROXIMITY_TKLOCK, "PROXIMITY_TKLOCK" },
{ MCE_SUBMODE_MALF, "MALF" },
{ 0,0 }
};
static char buff[128];
char *pos = buff;
char *end = buff + sizeof buff - 1;
auto inline void add(const char *str)
{
while( pos < end && *str )
*pos++ = *str++;
}
for( int i = 0; lut[i].name; ++i ) {
const char *tag = 0;
if( curr & lut[i].bit ) {
tag = (prev & lut[i].bit) ? "" : "+";
}
else if( prev & lut[i].bit ) {
tag = "-";
}
if( tag ) {
if( pos> buff ) add(" ");
add(tag);
add(lut[i].name);
}
}
if( pos == buff ) {
add("NONE");
}
*pos = 0;
return buff;
}
/** Convert submode_t bitmap to human readable string
*
* @param submode submode_t bitmap
*
* @return human readable representation of submode
*/
const char *submode_repr(submode_t submode)
{
return submode_change_repr(submode, submode);
}
/** Convert system_state_t enum to human readable string
*
* @param state system_state_t enumeration value
*
* @return human readable representation of state
*/
const char *system_state_repr(system_state_t state)
{
const char *res = "UNKNOWN";
switch( state ) {
case MCE_SYSTEM_STATE_UNDEF: res = "UNDEF"; break;
case MCE_SYSTEM_STATE_SHUTDOWN: res = "SHUTDOWN"; break;
case MCE_SYSTEM_STATE_USER: res = "USER"; break;
case MCE_SYSTEM_STATE_ACTDEAD: res = "ACTDEAD"; break;
case MCE_SYSTEM_STATE_REBOOT: res = "REBOOT"; break;
case MCE_SYSTEM_STATE_BOOT: res = "BOOT"; break;
default: break;
}
return res;
}
/** Convert devicelock_state_t enum to human readable string
*
* @param state devicelock_state_t enumeration value
*
* @return human readable representation of state
*/
const char *devicelock_state_repr(devicelock_state_t state)
{
const char *res = "unknown";
switch( state ) {
case DEVICELOCK_STATE_UNLOCKED: res = "unlocked"; break;
case DEVICELOCK_STATE_LOCKED: res = "locked"; break;
case DEVICELOCK_STATE_UNDEFINED: res = "undefined"; break;
default: break;
}
return res;
}
/** Convert thermal_state_t enum to human readable string
*
* @param state thermal state as thermal_state_t type
*
* @return human readable representation of state
*/
const char *thermal_state_repr(thermal_state_t state)
{
const char *res = "unknown";
switch( state ) {
case THERMAL_STATE_UNDEF: res = "undef"; break;
case THERMAL_STATE_OK: res = "ok"; break;
case THERMAL_STATE_OVERHEATED: res = "overheated"; break;
default: break;
}
return res;
}
/** Convert uiexception_type_t enum to human readable string
*
* Note that while uiexception_type_t actually is a bitmask
* and this function is expected to be used in situations
* where at maximum one bit is set.
*
* @param type uiexception_type_t exception stata
*
* @return human readable representation of type
*/
const char *uiexception_type_repr(uiexception_type_t type)
{
const char *res = "unknown";
switch( type ) {
case UIEXCEPTION_TYPE_NONE: res = "none"; break;
case UIEXCEPTION_TYPE_LINGER: res = "linger"; break;
case UIEXCEPTION_TYPE_CALL: res = "call"; break;
case UIEXCEPTION_TYPE_ALARM: res = "alarm"; break;
case UIEXCEPTION_TYPE_NOTIF: res = "notif"; break;
case UIEXCEPTION_TYPE_NOANIM: res = "noanim"; break;
default: break;
}
return res;
}
/** Convert uiexception_type_t enum to dbus argument string
*
* Note that while uiexception_type_t actually is a bitmask
* and this function is expected to be used in situations
* where at maximum one bit is set.
*
* @param type uiexception_type_t exception stata
*
* @return representation of type for use over dbus
*/
const char *uiexception_type_to_dbus(uiexception_type_t type)
{
const char *res = MCE_BLANKING_POLICY_DEFAULT_STRING;
switch( type ) {
case UIEXCEPTION_TYPE_NOTIF:
case UIEXCEPTION_TYPE_NOANIM:
res = MCE_BLANKING_POLICY_NOTIFICATION_STRING;
break;
case UIEXCEPTION_TYPE_ALARM:
res = MCE_BLANKING_POLICY_ALARM_STRING;
break;
case UIEXCEPTION_TYPE_CALL:
res = MCE_BLANKING_POLICY_CALL_STRING;
break;
case UIEXCEPTION_TYPE_LINGER:
res = MCE_BLANKING_POLICY_LINGER_STRING;
break;
case UIEXCEPTION_TYPE_NONE:
break;
default:
mce_log(LL_WARN, "unknown blanking policy; using default");
break;
}
return res;
}
/** Convert service_state_t enum to human readable string
*
* @param state service_state_t enumeration value
*
* @return human readable representation of state
*/
const char *service_state_repr(service_state_t state)
{
const char *res = "unknown";
switch( state ) {
case SERVICE_STATE_UNDEF: res = "undefined"; break;
case SERVICE_STATE_STOPPED: res = "stopped"; break;
case SERVICE_STATE_RUNNING: res = "running"; break;
default: break;
}
return res;
}
/** Convert usb_cable_state_t enum to human readable string
*
* @param state usb_cable_state_t enumeration value
*
* @return human readable representation of state
*/
const char *usb_cable_state_repr(usb_cable_state_t state)
{
const char *res = "unknown";
switch( state ) {
case USB_CABLE_UNDEF: res = "undefined"; break;
case USB_CABLE_DISCONNECTED: res = "disconnected"; break;
case USB_CABLE_CONNECTED: res = "connected"; break;
case USB_CABLE_ASK_USER: res = "ask_user"; break;
default: break;
}
return res;
}
/** Convert usb_cable_state_t enum to dbus argument string
*
* @param state usb_cable_state_t enumeration value
*
* @return representation of state for use over dbus
*/
const char *usb_cable_state_to_dbus(usb_cable_state_t state)
{
const char *res = MCE_USB_CABLE_STATE_UNKNOWN;
switch( state ) {
case USB_CABLE_DISCONNECTED:
res = MCE_USB_CABLE_STATE_DISCONNECTED;
break;
case USB_CABLE_ASK_USER:
case USB_CABLE_CONNECTED:
res = MCE_USB_CABLE_STATE_CONNECTED;
break;
default:
break;
}
return res;
}
/** Convert human readable name to charger_type_t enum
*
* @param name human readable charger type name
*
* @return charger_type_t enumeration value, or CHARGER_TYPE_INVALID
*/
charger_type_t
charger_type_parse(const char *name)
{
charger_type_t type = CHARGER_TYPE_INVALID;
if( !name )
mce_log(LL_WARN, "invalid charger type: %s", "null");
else if( !strcmp(name, "none") )
type = CHARGER_TYPE_NONE;
else if( !strcmp(name, "usb") )
type = CHARGER_TYPE_USB;
else if( !strcmp(name, "dcp") )
type = CHARGER_TYPE_DCP;
else if( !strcmp(name, "hwdcp") )
type = CHARGER_TYPE_HVDCP;
else if( !strcmp(name, "cdp") )
type = CHARGER_TYPE_CDP;
else if( !strcmp(name, "wireless") )
type = CHARGER_TYPE_WIRELESS;
else if( !strcmp(name, "other") )
type = CHARGER_TYPE_OTHER;
else
mce_log(LL_WARN, "invalid charger type: %s", name);
return type;
}
/** Convert charger_type_t enum to human readable string
*
* @param type charger_type_t enumeration value
*
* @return human readable representation of type
*/
const char *
charger_type_repr(charger_type_t type)
{
const char *repr = "invalid";
switch( type ) {
case CHARGER_TYPE_NONE: repr = "none"; break;
case CHARGER_TYPE_USB: repr = "usb"; break;
case CHARGER_TYPE_DCP: repr = "dcp"; break;
case CHARGER_TYPE_HVDCP: repr = "hwdcp"; break;
case CHARGER_TYPE_CDP: repr = "cdp"; break;
case CHARGER_TYPE_WIRELESS: repr = "wireless"; break;
case CHARGER_TYPE_OTHER: repr = "other"; break;
default: break;
}
return repr;
}
/** Convert charger_type_t enum to dbus argument string
*
* @param type charger_type_t enumeration value
*
* @return representation of type for use over dbus
*/
const char *
charger_type_to_dbus(charger_type_t type)
{
const char *repr = MCE_CHARGER_TYPE_OTHER;
switch( type ) {
case CHARGER_TYPE_INVALID:
case CHARGER_TYPE_NONE: repr = MCE_CHARGER_TYPE_NONE; break;
case CHARGER_TYPE_USB: repr = MCE_CHARGER_TYPE_USB; break;
case CHARGER_TYPE_DCP: repr = MCE_CHARGER_TYPE_DCP; break;
case CHARGER_TYPE_HVDCP: repr = MCE_CHARGER_TYPE_HVDCP; break;
case CHARGER_TYPE_CDP: repr = MCE_CHARGER_TYPE_CDP; break;
case CHARGER_TYPE_WIRELESS: repr = MCE_CHARGER_TYPE_WIRELESS; break;
default: break;
}
return repr;
}
/** Convert charger_state_t enum to human readable string
*
* @param state charger_state_t enumeration value
*
* @return human readable representation of state
*/
const char *charger_state_repr(charger_state_t state)
{
const char *res = "unknown";
switch( state ) {
case CHARGER_STATE_UNDEF: res = "undefined"; break;
case CHARGER_STATE_OFF: res = "off"; break;
case CHARGER_STATE_ON: res = "on"; break;
default: break;
}
return res;
}
/** Convert charger_state_t enum to dbus argument string
*
* @param state charger_state_t enumeration value
*
* @return representation of state for use over dbus
*/
const char *charger_state_to_dbus(charger_state_t state)
{
const char *res = MCE_CHARGER_STATE_UNKNOWN;
switch( state ) {
case CHARGER_STATE_OFF:
res = MCE_CHARGER_STATE_OFF;
break;
case CHARGER_STATE_ON:
res = MCE_CHARGER_STATE_ON;
break;
default:
break;
}
return res;
}
/** Convert camera_button_state_t enum to human readable string
*
* @param state camera_button_state_t enumeration value
*
* @return human readable representation of state
*/
const char *camera_button_state_repr(camera_button_state_t state)
{
const char *res = "unknown";
switch( state ) {
case CAMERA_BUTTON_UNDEF: res = "undef"; break;
case CAMERA_BUTTON_UNPRESSED: res = "unpressed"; break;
case CAMERA_BUTTON_LAUNCH: res = "launch"; break;
default: break;
}
return res;
}
/** Convert audio_route_t enum to human readable string
*
* @param state audio_route_t enumeration value
*
* @return human readable representation of state
*/
const char *audio_route_repr(audio_route_t state)
{
const char *res = "unknown";
switch( state ) {
case AUDIO_ROUTE_UNDEF: res = "undef"; break;
case AUDIO_ROUTE_HANDSET: res = "handset"; break;
case AUDIO_ROUTE_SPEAKER: res = "speaker"; break;
case AUDIO_ROUTE_HEADSET: res = "headset"; break;
default: break;
}
return res;
}
/** Convert tklock_request_t enum to human readable string
*
* @param state tklock_request_t enumeration value
*
* @return human readable representation of state
*/
const char *tklock_request_repr(tklock_request_t state)
{
const char *res = "unknown";
switch( state ) {
case TKLOCK_REQUEST_UNDEF: res = "undef"; break;
case TKLOCK_REQUEST_OFF: res = "off"; break;
case TKLOCK_REQUEST_OFF_DELAYED: res = "off_delayed"; break;
case TKLOCK_REQUEST_OFF_PROXIMITY: res = "off_proximity"; break;
case TKLOCK_REQUEST_ON: res = "on"; break;
case TKLOCK_REQUEST_ON_DIMMED: res = "on_dimmed"; break;
case TKLOCK_REQUEST_ON_PROXIMITY: res = "on_proximity"; break;
case TKLOCK_REQUEST_TOGGLE: res = "toggle"; break;
case TKLOCK_REQUEST_ON_DELAYED: res = "on_delayed"; break;
default: break;
}
return res;
}
/** Conver tklock status code from system ui to human readable string
*
* @param status TKLOCK_xxx value defined in mode-names.h from mce-dev.
*
* @return human readable representation of status
*/
const char *tklock_status_repr(int status)
{
const char *repr = "TKLOCK_UNKNOWN";
switch( status ) {
case TKLOCK_UNLOCK: repr = "TKLOCK_UNLOCK"; break;
case TKLOCK_RETRY: repr = "TKLOCK_RETRY"; break;
case TKLOCK_TIMEOUT: repr = "TKLOCK_TIMEOUT"; break;
case TKLOCK_CLOSED: repr = "TKLOCK_CLOSED"; break;
default: break;
}
return repr;
}
/** Convert battery_state_t enum to human readable string
*
* @param state battery_state_t enumeration value
*
* @return human readable representation of state
*/
const char *
battery_state_repr(battery_state_t state)
{
const char *repr = "invalid";
switch( state ) {
case BATTERY_STATE_UNKNOWN: repr = "unknown"; break;
case BATTERY_STATE_CHARGING: repr = "charging"; break;
case BATTERY_STATE_DISCHARGING: repr = "discharging"; break;
case BATTERY_STATE_NOT_CHARGING: repr = "not_charging"; break;
case BATTERY_STATE_FULL: repr = "full"; break;
default: break;
}
return repr;
}
/** Convert battery_state_t enum to dbus argument string
*
* @param state battery_state_t enumeration value
*
* @return representation of state for use over dbus
*/
const char *
battery_state_to_dbus(battery_state_t state)
{
const char *res = MCE_BATTERY_STATE_UNKNOWN;
switch( state ) {
case BATTERY_STATE_CHARGING:
res = MCE_BATTERY_STATE_CHARGING;
break;
case BATTERY_STATE_DISCHARGING:
res = MCE_BATTERY_STATE_DISCHARGING;
break;
case BATTERY_STATE_NOT_CHARGING:
res = MCE_BATTERY_STATE_NOT_CHARGING;
break;
case BATTERY_STATE_FULL:
res = MCE_BATTERY_STATE_FULL;
break;
default:
break;
}
return res;
}
/** Convert battery_status_t enum to human readable string
*
* @param state battery_status_t enumeration value
*
* @return human readable representation of state
*/
const char *battery_status_repr(battery_status_t state)
{
const char *res = "unknown";
switch( state ) {
case BATTERY_STATUS_UNDEF: res = "undefined"; break;
case BATTERY_STATUS_FULL: res = "full"; break;
case BATTERY_STATUS_OK: res = "ok"; break;
case BATTERY_STATUS_LOW: res = "low"; break;
case BATTERY_STATUS_EMPTY: res = "empty"; break;
default: break;
}
return res;
}
/** Convert battery_status_t enum to dbus argument string
*
* @param state battery_status_t enumeration value
*
* @return representation of state for use over dbus
*/
const char *battery_status_to_dbus(battery_status_t state)
{
const char *res = MCE_BATTERY_STATUS_UNKNOWN;
switch( state ) {
case BATTERY_STATUS_FULL:
res = MCE_BATTERY_STATUS_FULL;
break;
case BATTERY_STATUS_OK:
res = MCE_BATTERY_STATUS_OK;
break;
case BATTERY_STATUS_LOW:
res = MCE_BATTERY_STATUS_LOW;
break;
case BATTERY_STATUS_EMPTY:
res = MCE_BATTERY_STATUS_EMPTY;
break;
default:
break;
}
return res;
}
/** Convert alarm_ui_state_t enum to human readable string
*
* @param state alarm_ui_state_t enumeration value
*
* @return human readable representation of state
*/
const char *alarm_state_repr(alarm_ui_state_t state)
{
const char *res = "UNKNOWN";
switch( state ) {
case MCE_ALARM_UI_INVALID_INT32: res = "INVALID"; break;
case MCE_ALARM_UI_OFF_INT32: res = "OFF"; break;
case MCE_ALARM_UI_RINGING_INT32: res = "RINGING"; break;
case MCE_ALARM_UI_VISIBLE_INT32: res = "VISIBLE"; break;
default: break;
}
return res;
}
/** Mapping of call state integer <-> call state string */
static const mce_translation_t call_state_translation[] =
{
{
.number = CALL_STATE_NONE,
.string = MCE_CALL_STATE_NONE
},
{
.number = CALL_STATE_RINGING,
.string = MCE_CALL_STATE_RINGING,
},
{
.number = CALL_STATE_ACTIVE,
.string = MCE_CALL_STATE_ACTIVE,
},
{
.number = CALL_STATE_SERVICE,
.string = MCE_CALL_STATE_SERVICE
},
{ /* MCE_INVALID_TRANSLATION marks the end of this array */
.number = MCE_INVALID_TRANSLATION,
.string = MCE_CALL_STATE_NONE
}
};
/** MCE call state number to string on D-Bus
*/
const char *call_state_to_dbus(call_state_t state)
{
return mce_translate_int_to_string(call_state_translation, state);
}
/** String from D-Bus to MCE call state number */
call_state_t call_state_from_dbus(const char *name)
{
return mce_translate_string_to_int(call_state_translation, name);
}
/** MCE call state number to string (for diagnostic logging)
*/
const char *call_state_repr(call_state_t state)
{
const char *repr = "invalid";
switch( state ) {
case CALL_STATE_NONE:
repr = MCE_CALL_STATE_NONE;
break;
case CALL_STATE_RINGING:
repr = MCE_CALL_STATE_RINGING;
break;
case CALL_STATE_ACTIVE:
repr = MCE_CALL_STATE_ACTIVE;
break;
case CALL_STATE_SERVICE:
repr = MCE_CALL_STATE_SERVICE;
break;
case CALL_STATE_IGNORED:
repr = "ignored";
break;
default:
break;
}
return repr;
}
/** Mapping of call type integer <-> call type string */
static const mce_translation_t call_type_translation[] =
{
{
.number = CALL_TYPE_NORMAL,
.string = MCE_NORMAL_CALL
},
{
.number = CALL_TYPE_EMERGENCY,
.string = MCE_EMERGENCY_CALL
},
{ /* MCE_INVALID_TRANSLATION marks the end of this array */
.number = MCE_INVALID_TRANSLATION,
.string = MCE_NORMAL_CALL
}
};
/** MCE call type number to string
*/
const char *call_type_repr(call_type_t type)
{
return mce_translate_int_to_string(call_type_translation, type);
}
/** String to MCE call type number
*/
call_type_t call_type_parse(const char *name)
{
return mce_translate_string_to_int(call_type_translation, name);
}
/** Helper for getting cover_state_t in human readable form
*
* @param state cover state enum value
*
* @return enum name without "COVER_" prefix
*/
const char *cover_state_repr(cover_state_t state)
{
const char *res = "UNKNOWN";
switch( state ) {
case COVER_UNDEF: res = "UNDEF"; break;
case COVER_CLOSED: res = "CLOSED"; break;
case COVER_OPEN: res = "OPEN"; break;
default: break;
}
return res;
}
/** Proximity state enum to human readable string
*
* @param state Cover state enumeration value
*
* @return cover state as human readable proximity state name
*/
const char *proximity_state_repr(cover_state_t state)
{
const char *repr = "unknown";
switch( state ) {
case COVER_UNDEF: repr = "undefined"; break;
case COVER_CLOSED: repr = "covered"; break;
case COVER_OPEN: repr = "not covered"; break;
default:
break;
}
return repr;
}
/** Display state to human readable string
*/
const char *display_state_repr(display_state_t state)
{
const char *repr = "UNKNOWN";
switch( state ) {
case MCE_DISPLAY_UNDEF: repr = "UNDEF"; break;
case MCE_DISPLAY_OFF: repr = "OFF"; break;
case MCE_DISPLAY_LPM_OFF: repr = "LPM_OFF"; break;
case MCE_DISPLAY_LPM_ON: repr = "LPM_ON"; break;
case MCE_DISPLAY_DIM: repr = "DIM"; break;
case MCE_DISPLAY_ON: repr = "ON"; break;
case MCE_DISPLAY_POWER_UP: repr = "POWER_UP"; break;
case MCE_DISPLAY_POWER_DOWN: repr = "POWER_DOWN"; break;
default: break;
}
return repr;
}
/** Translate orientation state to human readable form */
const char *orientation_state_repr(orientation_state_t state)
{
const char *name = "UNKNOWN";
switch( state ) {
case MCE_ORIENTATION_UNDEFINED: name = "UNDEFINED"; break;
case MCE_ORIENTATION_LEFT_UP: name = "LEFT_UP"; break;
case MCE_ORIENTATION_RIGHT_UP: name = "RIGHT_UP"; break;
case MCE_ORIENTATION_BOTTOM_UP: name = "BOTTOM_UP"; break;
case MCE_ORIENTATION_BOTTOM_DOWN: name = "BOTTOM_DOWN"; break;
case MCE_ORIENTATION_FACE_DOWN: name = "FACE_DOWN"; break;
case MCE_ORIENTATION_FACE_UP: name = "FACE_UP"; break;
default: break;
}
return name;
}
/** Translate key state to human readable form */
const char *key_state_repr(key_state_t state)
{
const char *repr = "UNKNOWN";
switch( state ) {
case KEY_STATE_UNDEF: repr = "UNDEF"; break;
case KEY_STATE_RELEASED: repr = "RELEASED"; break;
case KEY_STATE_PRESSED: repr = "PRESSED"; break;
default: break;
}
return repr;
}
/** Translate tristate to human readable form */
const char *tristate_repr(tristate_t state)
{
const char *repr = "invalid";
switch( state ) {
case TRISTATE_UNKNOWN: repr = "unknown"; break;
case TRISTATE_FALSE: repr = "false"; break;
case TRISTATE_TRUE: repr = "true"; break;
default: break;
}
return repr;
}
/** Lookup table for fpstate_t <--> string */
static const mce_translation_t fpstate_lut[] =
{
{ FPSTATE_UNSET, "FPSTATE_UNSET" },
{ FPSTATE_ENUMERATING, "FPSTATE_ENUMERATING" },
{ FPSTATE_IDLE, "FPSTATE_IDLE" },
{ FPSTATE_ENROLLING, "FPSTATE_ENROLLING" },
{ FPSTATE_IDENTIFYING, "FPSTATE_IDENTIFYING" },
{ FPSTATE_REMOVING, "FPSTATE_REMOVING" },
{ FPSTATE_VERIFYING, "FPSTATE_VERIFYING" },
{ FPSTATE_ABORTING, "FPSTATE_ABORTING" },
{ FPSTATE_TERMINATING, "FPSTATE_TERMINATING" },
// sentinel
{ MCE_INVALID_TRANSLATION, 0 }
};
/** Parse fpd state from dbus string */
fpstate_t fpstate_parse(const char *name)
{
return mce_translate_string_to_int_with_default(fpstate_lut,
name,
FPSTATE_UNSET);
}
/** Translate fpd state to human readable form */
const char *fpstate_repr(fpstate_t state)
{
return mce_translate_int_to_string_with_default(fpstate_lut,
state,
"FPSTATE_UNKNOWN");
}
/** Translate level enum to human readable string
*
* Note: Also used as argument for the change signal and thus
* changes here can cause API breaks.
*/
const char *
memnotify_level_repr(memnotify_level_t lev)
{
static const char * const lut[MEMNOTIFY_LEVEL_COUNT] =
{
[MEMNOTIFY_LEVEL_NORMAL] = MCE_MEMORY_LEVEL_NORMAL,
[MEMNOTIFY_LEVEL_WARNING] = MCE_MEMORY_LEVEL_WARNING,
[MEMNOTIFY_LEVEL_CRITICAL] = MCE_MEMORY_LEVEL_CRITICAL,
[MEMNOTIFY_LEVEL_UNKNOWN] = MCE_MEMORY_LEVEL_UNKNOWN,
};
return (lev < MEMNOTIFY_LEVEL_COUNT) ? lut[lev] : "undefined";
}
static void
mce_datapipe_install_handlers(datapipe_handler_t *bindings)
{
if( !bindings )
goto EXIT;
for( size_t i = 0; bindings[i].datapipe; ++i ) {
if( bindings[i].bound )
continue;
if( bindings[i].filter_cb )
datapipe_add_filter(bindings[i].datapipe,
bindings[i].filter_cb);
if( bindings[i].input_cb )
datapipe_add_input_trigger(bindings[i].datapipe,
bindings[i].input_cb);
if( bindings[i].output_cb )
datapipe_add_output_trigger(bindings[i].datapipe,
bindings[i].output_cb);
bindings[i].bound = true;
}
EXIT:
return;
}
static void
mce_datapipe_remove_handlers(datapipe_handler_t *bindings)
{
if( !bindings )
goto EXIT;
for( size_t i = 0; bindings[i].datapipe; ++i ) {
if( !bindings[i].bound )
continue;
if( bindings[i].filter_cb )
datapipe_remove_filter(bindings[i].datapipe,
bindings[i].filter_cb);
if( bindings[i].input_cb )
datapipe_remove_input_trigger(bindings[i].datapipe,
bindings[i].input_cb);
if( bindings[i].output_cb )
datapipe_remove_output_trigger(bindings[i].datapipe,
bindings[i].output_cb);
bindings[i].bound = false;
}
EXIT:
return;
}
static void
mce_datapipe_execute_handlers(datapipe_handler_t *bindings)
{
if( !bindings )
goto EXIT;
for( size_t i = 0; bindings[i].datapipe; ++i ) {
if( !bindings[i].bound )
continue;
if( bindings[i].output_cb )
bindings[i].output_cb(bindings[i].datapipe->dp_cached_data);
}
EXIT:
return;
}
static gboolean mce_datapipe_execute_handlers_cb(gpointer aptr)
{
datapipe_bindings_t *self = aptr;
if( !self )
goto EXIT;
if( !self->execute_id )
goto EXIT;
self->execute_id = 0;
mce_log(LL_INFO, "module=%s", self->module ?: "unknown");
mce_datapipe_execute_handlers(self->handlers);
EXIT:
return FALSE;
}
/** Append triggers/filters to datapipes
*/
void mce_datapipe_init_bindings(datapipe_bindings_t *self)
{
mce_log(LL_INFO, "module=%s", self->module ?: "unknown");
/* Set up datapipe callbacks */
mce_datapipe_install_handlers(self->handlers);
/* Get initial values for output triggers from idle
* callback, i.e. when all modules have been loaded */
if( !self->execute_id )
self->execute_id = g_idle_add(mce_datapipe_execute_handlers_cb, self);
}
/** Remove triggers/filters from datapipes
*/
void mce_datapipe_quit_bindings(datapipe_bindings_t *self)
{
mce_log(LL_INFO, "module=%s", self->module ?: "unknown");
/* Remove the get initial values timer if still active */
if( self->execute_id ) {
g_source_remove(self->execute_id),
self->execute_id = 0;
}
/* Remove datapipe callbacks */
mce_datapipe_remove_handlers(self->handlers);
}
/** Helper for attempting to switch to active state
*/
void mce_datapipe_generate_activity(void)
{
datapipe_exec_full(&inactivity_event_pipe, GINT_TO_POINTER(FALSE));
}
/** Helper for switching to inactive state
*/
void mce_datapipe_generate_inactivity(void)
{
datapipe_exec_full(&inactivity_event_pipe, GINT_TO_POINTER(TRUE));
}