コード例 #1
0
ファイル: powerkey.c プロジェクト: ClementFan/mce
/**
 * 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;
}
コード例 #2
0
ファイル: camera.c プロジェクト: kimmoli/mce
/**
 * I/O monitor callback for the camera active state
 *
 * @param data The new data
 * @param bytes_read Unused
 * @return Always returns FALSE to return remaining chunks (if any)
 */
static gboolean camera_active_state_iomon_input_cb(gpointer data, gsize bytes_read)
{
	(void)bytes_read;

	if (!strncmp(data, MCE_CAMERA_ACTIVE, strlen(MCE_CAMERA_ACTIVE))) {
		execute_datapipe_output_triggers(&led_pattern_activate_pipe,
						 MCE_LED_PATTERN_CAMERA,
						 USE_INDATA);
	} else {
		execute_datapipe_output_triggers(&led_pattern_deactivate_pipe,
						 MCE_LED_PATTERN_CAMERA,
						 USE_INDATA);
	}

	return FALSE;
}
コード例 #3
0
ファイル: mce-io.c プロジェクト: android-808/mce
/** Detect suspend/resume cycle from CLOCK_MONOTONIC vs CLOCK_BOOTTIME
 */
static void io_detect_resume(void)
{
	static int64_t prev = 0;

	int64_t boot = io_get_boot_tick();
	int64_t mono = io_get_mono_tick();
	int64_t diff = boot - mono;

	int64_t skip = diff - prev;

	// small jitter can be due to scheduling too
	if( skip < 100 )
		goto EXIT;

	prev = diff;

	// no logging from the 1st time skip
	if( prev == skip )
		goto EXIT;

	mce_log(LL_DEVEL, "time skip: assume %"PRId64".%03"PRId64"s suspend",
		skip / 1000, skip % 1000);

	// notify in case some timers need re-evaluating
	execute_datapipe_output_triggers(&device_resumed_pipe,
					 &prev,
					 USE_INDATA);

EXIT:
	return;
}
コード例 #4
0
ファイル: mce-dsme.c プロジェクト: Vesuri/mce
/**
 * Request soft poweroff
 */
void request_soft_poweroff(void)
{
	mce_add_submode_int32(MCE_SOFTOFF_SUBMODE);
	execute_datapipe(&display_state_req_pipe,
			 GINT_TO_POINTER(MCE_DISPLAY_LPM_OFF),
			 USE_INDATA, CACHE_INDATA);

	/* Enable the soft poweroff LED pattern */
	execute_datapipe_output_triggers(&led_pattern_activate_pipe,
					 MCE_LED_PATTERN_DEVICE_SOFT_OFF,
					 USE_INDATA);
}
コード例 #5
0
ファイル: modetransition.c プロジェクト: guhl/mce
/**
 * Handle system state change
 *
 * @param data The system state stored in a pointer
 */
static void system_state_trigger(gconstpointer data)
{
	static system_state_t old_system_state = MCE_STATE_UNDEF;
	system_state_t system_state = GPOINTER_TO_INT(data);

	switch (system_state) {
	case MCE_STATE_USER:
		break;

	case MCE_STATE_SHUTDOWN:
	case MCE_STATE_REBOOT:
		/* Actions to perform when shutting down/rebooting
		 */
		switch( old_system_state ) {
		case MCE_STATE_USER:
		case MCE_STATE_BOOT:
		case MCE_STATE_UNDEF:
		case MCE_STATE_ACTDEAD:
			execute_datapipe_output_triggers(&led_pattern_deactivate_pipe, MCE_LED_PATTERN_DEVICE_ON, USE_INDATA);
			execute_datapipe_output_triggers(&led_pattern_activate_pipe, MCE_LED_PATTERN_POWER_OFF, USE_INDATA);
			break;

		default:
			break;
		}

		/* If we're shutting down/rebooting from actdead or
		 * user mode, ui side will do shutdown animation.
		 * Unblank the screen to make it visible. */
		switch( old_system_state ) {
		case MCE_STATE_USER:
		case MCE_STATE_ACTDEAD:
			execute_datapipe(&display_state_req_pipe,
					 GINT_TO_POINTER(MCE_DISPLAY_ON),
					 USE_INDATA, CACHE_INDATA);
			break;

		default:
			break;
		}
		break;

	case MCE_STATE_ACTDEAD:
		break;

	case MCE_STATE_UNDEF:
		goto EXIT;

	default:
		break;
	}

	mce_log(LL_DEBUG,
		"dsmestate set to: %d (old: %d)",
		system_state, old_system_state);

	old_system_state = system_state;

EXIT:
	return;
}
コード例 #6
0
ファイル: mce-dsme.c プロジェクト: g7/mce
/**
 * Callback for pending I/O from dsmesock
 *
 * XXX: is the error policy reasonable?
 *
 * @param source Unused
 * @param condition Unused
 * @param data Unused
 * @return TRUE on success, FALSE on failure
 */
static gboolean mce_dsme_iowatch_cb(GIOChannel *source,
				    GIOCondition condition,
				    gpointer data)
{
	gboolean keep_going = TRUE;
	dsmemsg_generic_t *msg = 0;

	DSM_MSGTYPE_STATE_CHANGE_IND *msg2;

	(void)source;
	(void)data;

	if( condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) ) {
		if( !mce_dsme_shutting_down() )
			mce_log(LL_CRIT, "DSME socket hangup/error");
		keep_going = FALSE;
		goto EXIT;
	}

	if( !(msg = dsmesock_receive(mce_dsme_connection)) )
		goto EXIT;

	if( DSMEMSG_CAST(DSM_MSGTYPE_CLOSE, msg) ) {
		if( !mce_dsme_shutting_down() )
			mce_log(LL_WARN, "DSME socket closed");
		keep_going = FALSE;
	}
	else if( DSMEMSG_CAST(DSM_MSGTYPE_PROCESSWD_PING, msg) ) {
		mce_dsme_send_pong();
	}
	else if( (msg2 = DSMEMSG_CAST(DSM_MSGTYPE_STATE_CHANGE_IND, msg)) ) {
		system_state_t prev = system_state;
		system_state = mce_dsme_normalise_system_state(msg2->state);
		mce_log(LL_DEVEL, "DSME device state change: %d", system_state);

		/* If we're changing to a different state,
		 * add the transition flag, UNLESS the old state
		 * was MCE_STATE_UNDEF
		 */
		if( system_state != prev && prev != MCE_STATE_UNDEF )
			mce_add_submode_int32(MCE_TRANSITION_SUBMODE);

		switch (system_state) {
		case MCE_STATE_USER:
			execute_datapipe_output_triggers(&led_pattern_activate_pipe, MCE_LED_PATTERN_DEVICE_ON, USE_INDATA);
			break;

		case MCE_STATE_ACTDEAD:
		case MCE_STATE_BOOT:
		case MCE_STATE_UNDEF:
			break;

		case MCE_STATE_SHUTDOWN:
		case MCE_STATE_REBOOT:
			execute_datapipe_output_triggers(&led_pattern_deactivate_pipe, MCE_LED_PATTERN_DEVICE_ON, USE_INDATA);
			break;

		default:
			break;
		}

		mce_log(LL_DEVEL, "system_state: %s -> %s",
			system_state_repr(prev),
			system_state_repr(system_state));

		execute_datapipe(&system_state_pipe,
				 GINT_TO_POINTER(system_state),
				 USE_INDATA, CACHE_INDATA);
	}
	else {
		mce_log(LL_DEBUG, "Unhandled message type %s (0x%x) received from DSME",
			mce_dsme_msg_type_repr(msg->type_),
			msg->type_); /* <- unholy access of a private member */
	}

EXIT:
	free(msg);

	if( !keep_going ) {
		if( !mce_dsme_shutting_down() ) {
			mce_log(LL_WARN, "DSME i/o notifier disabled;"
				" assuming dsme was stopped");
		}

		/* mark notifier as removed */
		mce_dsme_iowatch_id = 0;

		/* close and wait for possible dsme restart */
		mce_dsme_disconnect();
	}

	return keep_going;
}
コード例 #7
0
/** Process accumulated upower battery status changes
 *
 * @param user_data (not used)
 *
 * @return FALSE (to stop timer from repeating)
 */
static gboolean
mcebat_update_cb(gpointer user_data)
{
    (void)user_data;

    if( !mcebat_update_id )
        return FALSE;

    mce_log(LL_INFO, "----( state machine )----");

    /* Get a copy of current status */
    MceBattery prev = mcebat;

    /* Update from UPower based information */
    upowbat_update();
    mcebat_update_from_upowbat();

    /* Process changes */
    if( mcebat.charger != prev.charger ) {
        mce_log(LL_INFO, "charger: %s -> %s",
                charger_state_repr(prev.charger),
                charger_state_repr(mcebat.charger));

        /* Charger connected state */
        execute_datapipe(&charger_state_pipe, GINT_TO_POINTER(mcebat.charger),
                         USE_INDATA, CACHE_INDATA);

        /* Charging led pattern */
        if( mcebat.charger == CHARGER_STATE_ON ) {
            execute_datapipe_output_triggers(&led_pattern_activate_pipe,
                                             MCE_LED_PATTERN_BATTERY_CHARGING,
                                             USE_INDATA);
        }
        else {
            execute_datapipe_output_triggers(&led_pattern_deactivate_pipe,
                                             MCE_LED_PATTERN_BATTERY_CHARGING,
                                             USE_INDATA);
        }

        /* Generate activity */
        (void)execute_datapipe(&device_inactive_pipe, GINT_TO_POINTER(FALSE),
                               USE_INDATA, CACHE_INDATA);
    }

    if( mcebat.status != prev.status ) {
        mce_log(LL_INFO, "status: %d -> %d", prev.status, mcebat.status);

        /* Battery full led pattern */
        if( mcebat.status == BATTERY_STATUS_FULL ) {
            execute_datapipe_output_triggers(&led_pattern_activate_pipe,
                                             MCE_LED_PATTERN_BATTERY_FULL,
                                             USE_INDATA);
        }
        else {
            execute_datapipe_output_triggers(&led_pattern_deactivate_pipe,
                                             MCE_LED_PATTERN_BATTERY_FULL,
                                             USE_INDATA);
        }

#if SUPPORT_BATTERY_LOW_LED_PATTERN
        /* Battery low led pattern */
        if( mcebat.status == BATTERY_STATUS_LOW ||
            mcebat.status == BATTERY_STATUS_EMPTY ) {
            execute_datapipe_output_triggers(&led_pattern_activate_pipe,
                                             MCE_LED_PATTERN_BATTERY_LOW,
                                             USE_INDATA);
        }
        else {
            execute_datapipe_output_triggers(&led_pattern_deactivate_pipe,
                                             MCE_LED_PATTERN_BATTERY_LOW,
                                             USE_INDATA);
        }
#endif /* SUPPORT_BATTERY_LOW_LED_PATTERN */

        /* Battery charge state */
        execute_datapipe(&battery_status_pipe,
                         GINT_TO_POINTER(mcebat.status),
                         USE_INDATA, CACHE_INDATA);

    }

    if( mcebat.level != prev.level ) {
        mce_log(LL_INFO, "level: %d -> %d", prev.level, mcebat.level);

        /* Battery charge percentage */
        execute_datapipe(&battery_level_pipe,
                         GINT_TO_POINTER(mcebat.level),
                         USE_INDATA, CACHE_INDATA);
    }

    /* Clear the timer id and do not repeat */
    return mcebat_update_id = 0, FALSE;
}
コード例 #8
0
ファイル: mce-dsme.c プロジェクト: Vesuri/mce
/**
 * Callback for pending I/O from dsmesock
 *
 * XXX: is the error policy reasonable?
 *
 * @param source Unused
 * @param condition Unused
 * @param data Unused
 * @return TRUE on success, FALSE on failure
 */
static gboolean io_data_ready_cb(GIOChannel *source,
				 GIOCondition condition,
				 gpointer data)
{
	dsmemsg_generic_t *msg;
	DSM_MSGTYPE_STATE_CHANGE_IND *msg2;
	system_state_t oldstate = datapipe_get_gint(system_state_pipe);
	system_state_t newstate = MCE_STATE_UNDEF;

	(void)source;
	(void)condition;
	(void)data;

	if (dsme_disabled == TRUE)
		goto EXIT;

	if ((msg = (dsmemsg_generic_t *)dsmesock_receive(dsme_conn)) == NULL)
		goto EXIT;

        if (DSMEMSG_CAST(DSM_MSGTYPE_CLOSE, msg)) {
		/* DSME socket closed: try once to reopen;
		 * if that fails, exit
		 */
		mce_log(LL_ERR,
			"DSME socket closed; trying to reopen");

		if ((init_dsmesock()) == FALSE) {
			// FIXME: this is not how one should exit from mainloop
			mce_quit_mainloop();
			exit(EXIT_FAILURE);
		}
        } else if (DSMEMSG_CAST(DSM_MSGTYPE_PROCESSWD_PING, msg)) {
		dsme_send_pong();
        } else if ((msg2 = DSMEMSG_CAST(DSM_MSGTYPE_STATE_CHANGE_IND, msg))) {
		newstate = normalise_dsme_state(msg2->state);
		mce_log(LL_DEBUG,
			"DSME device state change: %d",
			newstate);

		/* If we're changing to a different state,
		 * add the transition flag, UNLESS the old state
		 * was MCE_STATE_UNDEF
		 */
		if ((oldstate != newstate) && (oldstate != MCE_STATE_UNDEF))
			mce_add_submode_int32(MCE_TRANSITION_SUBMODE);

		switch (newstate) {
		case MCE_STATE_USER:
			execute_datapipe_output_triggers(&led_pattern_activate_pipe, MCE_LED_PATTERN_DEVICE_ON, USE_INDATA);
			break;

		case MCE_STATE_ACTDEAD:
		case MCE_STATE_BOOT:
		case MCE_STATE_UNDEF:
			break;

		case MCE_STATE_SHUTDOWN:
		case MCE_STATE_REBOOT:
			execute_datapipe_output_triggers(&led_pattern_deactivate_pipe, MCE_LED_PATTERN_DEVICE_ON, USE_INDATA);
			break;

		default:
			break;
		}

		execute_datapipe(&system_state_pipe,
				 GINT_TO_POINTER(newstate),
				 USE_INDATA, CACHE_INDATA);
        } else {
		mce_log(LL_DEBUG,
			"Unknown message type (%x) received from DSME!",
			msg->type_); /* <- unholy access of a private member */
	}

	free(msg);

EXIT:
	return TRUE;
}