/** * Init function for the modetransition component * * @return TRUE on success, FALSE on failure */ gboolean mce_mode_init(void) { gboolean status = FALSE; /* Append triggers/filters to datapipes */ mce_mode_datapipe_init(); /* If the bootup file exists, mce has crashed / restarted; * since it exists in /var/run it will be removed when we reboot. * * If the file doesn't exist, create it to ensure that * restarting mce doesn't get mce stuck in the transition submode */ if (g_access(MCE_BOOTUP_FILENAME, F_OK) == -1) { if (errno == ENOENT) { mce_log(LL_DEBUG, "Bootup mode enabled"); mce_add_submode_int32(MCE_SUBMODE_TRANSITION); errno = 0; mce_write_string_to_file(MCE_BOOTUP_FILENAME, ENABLED_STRING); if (g_access(MALF_FILENAME, F_OK) == 0) { mce_add_submode_int32(MCE_SUBMODE_MALF); mce_log(LL_DEBUG, "Malf mode enabled"); if (g_access(MCE_MALF_FILENAME, F_OK) == -1) { if (errno != ENOENT) { mce_log(LL_CRIT, "access() failed: %s. Exiting.", g_strerror(errno)); goto EXIT; } mce_write_string_to_file(MCE_MALF_FILENAME, ENABLED_STRING); } } } else { mce_log(LL_CRIT, "access() failed: %s. Exiting.", g_strerror(errno)); goto EXIT; } } else { if (g_access(MALF_FILENAME, F_OK) == 0) { if (g_access(MCE_MALF_FILENAME, F_OK) == 0) { mce_add_submode_int32(MCE_SUBMODE_MALF); mce_log(LL_DEBUG, "Malf mode enabled"); } } else if ((errno == ENOENT) && (g_access(MCE_MALF_FILENAME, F_OK) == 0)) { g_remove(MCE_MALF_FILENAME); } } status = TRUE; EXIT: return status; }
/** * 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); }
/** * 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; }
/** * 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; }