/** * Setup doublepress timeout * * @return TRUE if the doublepress action was setup, * FALSE if no action was setup */ static gboolean setup_doublepress_timeout(void) { submode_t submode = mce_get_submode_int32(); gboolean status = FALSE; /* Only setup the doublepress timeout when needed */ if (doublepressaction == POWER_DISABLED) goto EXIT; cancel_doublepress_timeout(); /* If the tklock is enabled, but doublepress to unlock is disabled, * or if the tklock isn't enabled and short press to lock is enabled, * exit */ if (doublepressaction != POWER_DBUS_SIGNAL) { if ((submode & MCE_TKLOCK_SUBMODE) != 0) { if ((doublepressaction != POWER_TKLOCK_UNLOCK) && (doublepressaction != POWER_TKLOCK_BOTH)) goto EXIT; } else { if ((shortpressaction == POWER_TKLOCK_LOCK) || (shortpressaction == POWER_TKLOCK_BOTH)) goto EXIT; } } /* Setup new timeout */ doublepress_timeout_cb_id = g_timeout_add(doublepressdelay, doublepress_timeout_cb, NULL); status = TRUE; EXIT: return status; }
/** * Datapipe trigger for the charger state * * @param data TRUE if the charger was connected, * FALSE if the charger was disconnected */ static void charger_state_trigger(gconstpointer const data) { submode_t submode = mce_get_submode_int32(); charger_connected = GPOINTER_TO_INT(data); if ((submode & MCE_SOFTOFF_SUBMODE) != 0) { if (softoff_charger_connect_policy == SOFTOFF_CHARGER_CONNECT_WAKEUP) { request_soft_poweron(); } } }
/** * Datapipe trigger for the [power] key * * @param data A pointer to the input_event struct */ static void powerkey_trigger(gconstpointer const data) { system_state_t system_state = datapipe_get_gint(system_state_pipe); submode_t submode = mce_get_submode_int32(); struct input_event const *const *evp; struct input_event const *ev; /* Don't dereference until we know it's safe */ if (data == NULL) goto EXIT; evp = data; ev = *evp; if ((ev != NULL) && (ev->code == KEY_POWER)) { /* If set, the [power] key was pressed */ if (ev->value == 1) { mce_log(LL_DEBUG, "[power] pressed"); /* Are we waiting for a doublepress? */ if (doublepress_timeout_cb_id != 0) { handle_shortpress(); } else if ((system_state == MCE_STATE_ACTDEAD) || ((submode & MCE_SOFTOFF_SUBMODE) != 0)) { /* Setup new timeout */ execute_datapipe_output_triggers(&led_pattern_activate_pipe, MCE_LED_PATTERN_POWER_ON, USE_INDATA); /* Shorter delay for startup * than for shutdown */ setup_powerkey_timeout(mediumdelay); } else { setup_powerkey_timeout(longdelay); } } else if (ev->value == 0) { mce_log(LL_DEBUG, "[power] released"); /* Short key press */ if (powerkey_timeout_cb_id != 0) { handle_shortpress(); if ((system_state == MCE_STATE_ACTDEAD) || ((submode & MCE_SOFTOFF_SUBMODE) != 0)) { execute_datapipe_output_triggers(&led_pattern_deactivate_pipe, MCE_LED_PATTERN_POWER_ON, USE_INDATA); } } } } EXIT: return; }
/** * Logic for long key press * * @return TRUE on success, FALSE on failure */ static gboolean handle_longpress(void) { system_state_t state = datapipe_get_gint(system_state_pipe); alarm_ui_state_t alarm_ui_state = datapipe_get_gint(alarm_ui_state_pipe); submode_t submode = mce_get_submode_int32(); gboolean status = TRUE; /* Ignore keypress if the alarm UI is visible */ if ((alarm_ui_state == MCE_ALARM_UI_VISIBLE_INT32) || (alarm_ui_state == MCE_ALARM_UI_RINGING_INT32)) goto EXIT; /* Ignore if we're already shutting down/rebooting */ switch (state) { case MCE_STATE_SHUTDOWN: case MCE_STATE_REBOOT: status = FALSE; break; case MCE_STATE_ACTDEAD: request_powerup(); break; case MCE_STATE_USER: /* If softoff is enabled, wake up * Otherwise, perform long press action */ if ((submode & MCE_SOFTOFF_SUBMODE)) { request_soft_poweron(); } else { generic_powerkey_handler(longpressaction, longpresssignal); } break; default: /* If no special cases are needed, * just do a regular shutdown */ mce_log(LL_WARN, "Requesting shutdown; state: %d", state); request_normal_shutdown(); break; } EXIT: return status; }
/** * D-Bus callback for the init done notification signal * * @param msg The D-Bus message * @return TRUE on success, FALSE on failure */ static gboolean mce_dsme_init_done_cb(DBusMessage *const msg) { gboolean status = FALSE; (void)msg; mce_log(LL_DEVEL, "Received init done notification"); if ((mce_get_submode_int32() & MCE_TRANSITION_SUBMODE)) { mce_dsme_schedule_state_report(); } status = TRUE; //EXIT: return status; }
/** * D-Bus callback for the init done notification signal * * @param msg The D-Bus message * @return TRUE on success, FALSE on failure */ static gboolean init_done_dbus_cb(DBusMessage *const msg) { gboolean status = FALSE; (void)msg; mce_log(LL_DEBUG, "Received init done notification"); if ((mce_get_submode_int32() & MCE_TRANSITION_SUBMODE)) { setup_transition_timeout(); } status = TRUE; //EXIT: return status; }
/** * Generic logic for key presses * * @param action The action to take * @param dbus_signal A D-Bus signal to send */ static void generic_powerkey_handler(poweraction_t action, gchar *dbus_signal) { alarm_ui_state_t alarm_ui_state = datapipe_get_gint(alarm_ui_state_pipe); submode_t submode = mce_get_submode_int32(); /* Ignore keypress if the alarm UI is visible */ if ((alarm_ui_state == MCE_ALARM_UI_VISIBLE_INT32) || (alarm_ui_state == MCE_ALARM_UI_RINGING_INT32)) goto EXIT; switch (action) { case POWER_DISABLED: break; case POWER_POWEROFF: default: /* Do not shutdown if the tklock is active * or if we're in alarm state */ if ((submode & MCE_TKLOCK_SUBMODE) == 0) { mce_log(LL_WARN, "Requesting shutdown (action: %d)", action); request_normal_shutdown(); } break; case POWER_SOFT_POWEROFF: /* Only soft poweroff if the tklock isn't active */ if ((submode & MCE_TKLOCK_SUBMODE) == 0) { request_soft_poweroff(); } break; case POWER_TKLOCK_LOCK: /* Request enabling of touchscreen/keypad lock * if the tklock isn't already active */ if ((submode & MCE_TKLOCK_SUBMODE) == 0) { execute_datapipe(&tk_lock_pipe, GINT_TO_POINTER(LOCK_ON), USE_INDATA, CACHE_INDATA); } else if ((submode & MCE_MALF_SUBMODE) != 0) { execute_datapipe(&tk_lock_pipe, GINT_TO_POINTER(LOCK_OFF), USE_INDATA, CACHE_INDATA); } break; case POWER_TKLOCK_UNLOCK: /* Request disabling of touchscreen/keypad lock * if the tklock isn't already inactive */ if ((submode & MCE_TKLOCK_SUBMODE) != 0) { execute_datapipe(&tk_lock_pipe, GINT_TO_POINTER(LOCK_OFF), USE_INDATA, CACHE_INDATA); } break; case POWER_TKLOCK_BOTH: /* Request enabling of touchscreen/keypad lock * if the tklock isn't active, * and disabling if the tklock is active */ if ((submode & MCE_TKLOCK_SUBMODE) == 0) { execute_datapipe(&tk_lock_pipe, GINT_TO_POINTER(LOCK_ON), USE_INDATA, CACHE_INDATA); } else { execute_datapipe(&tk_lock_pipe, GINT_TO_POINTER(LOCK_OFF), USE_INDATA, CACHE_INDATA); } break; case POWER_DBUS_SIGNAL: /* Send a D-Bus signal */ dbus_send(NULL, MCE_REQUEST_PATH, MCE_REQUEST_IF, dbus_signal, NULL, DBUS_TYPE_INVALID); } EXIT: return; }
/** * Datapipe filter for inactivity * * @param data The unfiltered inactivity state; * TRUE if the device is inactive, * FALSE if the device is active * @return The filtered inactivity state; * TRUE if the device is inactive, * FALSE if the device is active */ static gpointer device_inactive_filter(gpointer data) { static gboolean old_device_inactive = FALSE; alarm_ui_state_t alarm_ui_state = datapipe_get_gint(alarm_ui_state_pipe); submode_t submode = mce_get_submode_int32(); cover_state_t proximity_state = proximity_state_get(); display_state_t display_state = display_state_get(); system_state_t system_state = datapipe_get_gint(system_state_pipe); call_state_t call_state = datapipe_get_gint(call_state_pipe); device_inactive = GPOINTER_TO_INT(data); /* nothing to filter if we are already inactive */ if( device_inactive ) goto EXIT; /* Never filter inactivity if display is in dimmed state. * * Whether we have arrived to dimmed state via expected or * unexpected routes, the touch input is active and ui side * event eater will ignore only the first event. If we do * not allow activity (and turn on the display) we will get * ui interaction in odd looking dimmed state that then gets * abruptly ended by blanking timer. */ if( display_state == MCE_DISPLAY_DIM ) goto EXIT; /* system state must be USER or ACT DEAD */ switch( system_state ) { case MCE_STATE_USER: case MCE_STATE_ACTDEAD: break; default: mce_log(LL_DEBUG, "system_state != USER|ACTDEAD" "; ignoring activity"); device_inactive = TRUE; goto EXIT; } /* tklock must be off, or there must be alarms or calls */ if( submode & MCE_TKLOCK_SUBMODE ) { gboolean have_alarms = FALSE; gboolean have_calls = FALSE; gboolean display_on = FALSE; switch( alarm_ui_state ) { case MCE_ALARM_UI_RINGING_INT32: case MCE_ALARM_UI_VISIBLE_INT32: have_alarms = TRUE; break; default: break; } switch( call_state ) { case CALL_STATE_RINGING: case CALL_STATE_ACTIVE: have_calls = TRUE; default: break; } if( display_state == MCE_DISPLAY_ON ) display_on = TRUE; if( !display_on && !have_alarms && !have_calls ) { mce_log(LL_DEBUG, "tklock enabled, no alarms or calls;" " ignoring activity"); device_inactive = TRUE; goto EXIT; } } /* if proximity is covered, display must not be off */ if( proximity_state == COVER_CLOSED ) { switch( display_state ) { case MCE_DISPLAY_OFF: case MCE_DISPLAY_LPM_OFF: case MCE_DISPLAY_LPM_ON: case MCE_DISPLAY_POWER_UP: case MCE_DISPLAY_POWER_DOWN: mce_log(LL_DEBUG, "display=off, proximity=covered; ignoring activity"); device_inactive = TRUE; goto EXIT; default: case MCE_DISPLAY_UNDEF: case MCE_DISPLAY_DIM: case MCE_DISPLAY_ON: break; } } EXIT: /* React to activity */ if( !device_inactive ) { call_activity_callbacks(); setup_inactivity_timeout(); } /* Handle inactivity state change */ if( old_device_inactive != device_inactive ) { old_device_inactive = device_inactive; send_inactivity_status(NULL); } /* Return filtered activity state */ return GINT_TO_POINTER(device_inactive); }