blob: 53df62d01e3fbb31bdb5334f8512bc7209694d43 [file] [log] [blame]
Norman James26072c02015-08-25 07:14:29 -05001#include <stdint.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <fcntl.h>
6#include <unistd.h>
7#include <sys/stat.h>
8#include <sys/mman.h>
Norman James8abb50c2015-09-16 10:58:16 -05009#include <syslog.h>
Norman James362a80f2015-09-14 14:04:39 -050010#include "interfaces/openbmc_intf.h"
Norman James10ff6a32015-08-27 14:24:17 -050011#include "openbmc.h"
12#include "gpio.h"
Norman Jamese2765102015-08-19 22:00:55 -050013
14/* ---------------------------------------------------------------------------------------------------- */
Norman James362a80f2015-09-14 14:04:39 -050015static const gchar* dbus_object_path = "/org/openbmc/control";
Norman James26072c02015-08-25 07:14:29 -050016static const gchar* dbus_name = "org.openbmc.control.Power";
17
Norman James32e74e22015-09-15 21:28:06 -050018//This object will use these GPIOs
Norman James3f97c5d2015-08-26 17:44:14 -050019GPIO power_pin = (GPIO){ "POWER_PIN" };
20GPIO pgood = (GPIO){ "PGOOD" };
Norman Jamese2765102015-08-19 22:00:55 -050021
22static GDBusObjectManagerServer *manager = NULL;
Norman Jamese2765102015-08-19 22:00:55 -050023
Norman James88872672015-09-21 16:51:35 -050024//guint tmp_pgood = 0;
25//guint last_pgood = 0;
26time_t pgood_timeout_start = 0;
Norman James362a80f2015-09-14 14:04:39 -050027
Norman Jamesce46e3e2015-08-30 22:25:55 -050028static gboolean poll_pgood(gpointer user_data)
29{
30 ControlPower *control_power = object_get_control_power((Object*)user_data);
31 Control* control = object_get_control((Object*)user_data);
32 EventLog* event_log = object_get_event_log((Object*)user_data);
Norman Jamesbd4abd12015-09-16 22:43:46 -050033
34 //send the heartbeat
Norman Jamesce46e3e2015-08-30 22:25:55 -050035 control_emit_heartbeat(control,dbus_name);
Norman James32e74e22015-09-15 21:28:06 -050036 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
Norman Jamesce46e3e2015-08-30 22:25:55 -050037
Norman James6a1283c2015-09-16 22:21:11 -050038 guint poll_int = control_get_poll_interval(control);
39 if (poll_int == 0)
40 {
Norman James88872672015-09-21 16:51:35 -050041 event_log_emit_event_log(event_log, LOG_ALERT, "Poll interval cannot be 0",0);
Norman James6a1283c2015-09-16 22:21:11 -050042 return FALSE;
43 }
Norman James88872672015-09-21 16:51:35 -050044 //handle timeout
45 time_t current_time = time(NULL);
46 if (difftime(current_time,pgood_timeout_start) > control_power_get_pgood_timeout(control_power)
47 && pgood_timeout_start != 0)
Norman James32e74e22015-09-15 21:28:06 -050048 {
Norman James88872672015-09-21 16:51:35 -050049 event_log_emit_event_log(event_log, LOG_ALERT, "Pgood poll timeout",0);
Norman Jamesbd4abd12015-09-16 22:43:46 -050050 // set timeout to 0 so timeout doesn't happen again
Norman James32e74e22015-09-15 21:28:06 -050051 control_power_set_pgood_timeout(control_power,0);
Norman James88872672015-09-21 16:51:35 -050052 pgood_timeout_start = 0;
Norman James8abb50c2015-09-16 10:58:16 -050053 return TRUE;
Norman James32e74e22015-09-15 21:28:06 -050054 }
Norman James362a80f2015-09-14 14:04:39 -050055 //For simulation, remove
Norman James88872672015-09-21 16:51:35 -050056 /*
Norman James362a80f2015-09-14 14:04:39 -050057 if (tmp_pgood!=last_pgood) {
58 if (tmp_pgood == 1) {
59 control_emit_goto_system_state(control,"POWERED_ON");
60 } else {
61 control_emit_goto_system_state(control,"POWERED_OFF");
Norman Jamesce46e3e2015-08-30 22:25:55 -050062 }
Norman James362a80f2015-09-14 14:04:39 -050063 }
Norman James88872672015-09-21 16:51:35 -050064
Norman James362a80f2015-09-14 14:04:39 -050065 last_pgood = tmp_pgood;
Norman James88872672015-09-21 16:51:35 -050066 */
Norman James32e74e22015-09-15 21:28:06 -050067 uint8_t gpio;
Norman James88872672015-09-21 16:51:35 -050068
69 int rc = gpio_open(&pgood);
70 rc = gpio_read(&pgood,&gpio);
71 gpio_close(&pgood);
Norman James32e74e22015-09-15 21:28:06 -050072 if (rc == GPIO_OK)
Norman James362a80f2015-09-14 14:04:39 -050073 {
Norman James32e74e22015-09-15 21:28:06 -050074 //if changed, set property and emit signal
75 if (gpio != control_power_get_pgood(control_power))
76 {
77 control_power_set_pgood(control_power,gpio);
78 if (gpio==0)
79 {
80 control_power_emit_power_lost(control_power);
81 control_emit_goto_system_state(control,"POWERED_OFF");
82 }
83 else
84 {
85 control_power_emit_power_good(control_power);
86 control_emit_goto_system_state(control,"POWERED_ON");
87 }
88 }
89 } else {
Norman James88872672015-09-21 16:51:35 -050090 event_log_emit_event_log(event_log, LOG_ALERT, "GPIO read error",rc);
Norman James6a1283c2015-09-16 22:21:11 -050091 //return FALSE;
Norman James32e74e22015-09-15 21:28:06 -050092 }
93 //pgood is not at desired state yet
Norman James88872672015-09-21 16:51:35 -050094 g_print("GPIO: %d; %d\n",gpio,control_power_get_state(control_power));
Norman James32e74e22015-09-15 21:28:06 -050095 if (gpio != control_power_get_state(control_power) &&
Norman James88872672015-09-21 16:51:35 -050096 control_power_get_pgood_timeout(control_power) > 0)
Norman James32e74e22015-09-15 21:28:06 -050097 {
Norman James88872672015-09-21 16:51:35 -050098 if (pgood_timeout_start == 0 ) {
99 pgood_timeout_start = current_time;
100 }
Norman James32e74e22015-09-15 21:28:06 -0500101 }
102 else
103 {
Norman James88872672015-09-21 16:51:35 -0500104 pgood_timeout_start = 0;
Norman James362a80f2015-09-14 14:04:39 -0500105 }
Norman Jamesce46e3e2015-08-30 22:25:55 -0500106 return TRUE;
107}
108
109
110
Norman Jamese2765102015-08-19 22:00:55 -0500111static gboolean
Norman James3f97c5d2015-08-26 17:44:14 -0500112on_set_power_state (ControlPower *pwr,
Norman Jamese2765102015-08-19 22:00:55 -0500113 GDBusMethodInvocation *invocation,
114 guint state,
115 gpointer user_data)
116{
Norman James362a80f2015-09-14 14:04:39 -0500117 Control* control = object_get_control((Object*)user_data);
Norman James32e74e22015-09-15 21:28:06 -0500118 EventLog* event_log = object_get_event_log((Object*)user_data);
119 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
Norman James3f97c5d2015-08-26 17:44:14 -0500120 if (state > 1)
121 {
122 g_dbus_method_invocation_return_dbus_error (invocation,
123 "org.openbmc.ControlPower.Error.Failed",
124 "Invalid power state");
125 return TRUE;
126 }
Norman James9e6acf92015-09-08 07:00:04 -0500127 // return from method call
128 control_power_complete_set_power_state(pwr,invocation);
Norman James3f97c5d2015-08-26 17:44:14 -0500129 if (state == control_power_get_state(pwr))
130 {
Norman James9e6acf92015-09-08 07:00:04 -0500131 g_print("Power already at requested state: %d\n",state);
Norman James3f97c5d2015-08-26 17:44:14 -0500132 }
Norman James9e6acf92015-09-08 07:00:04 -0500133 else
134 {
135 g_print("Set power state: %d\n",state);
Norman James362a80f2015-09-14 14:04:39 -0500136 //temporary until real hardware works
Norman James88872672015-09-21 16:51:35 -0500137 //tmp_pgood = state;
Norman James32e74e22015-09-15 21:28:06 -0500138 int error = 0;
139 do {
140 error = gpio_open(&power_pin);
Norman James88872672015-09-21 16:51:35 -0500141 if (error != GPIO_OK) { break; }
Norman James32e74e22015-09-15 21:28:06 -0500142 error = gpio_write(&power_pin,!state);
Norman James88872672015-09-21 16:51:35 -0500143 if (error != GPIO_OK) { break; }
Norman James32e74e22015-09-15 21:28:06 -0500144 gpio_close(&power_pin);
145 control_power_set_state(pwr,state);
146 if (state == 1) {
147 control_emit_goto_system_state(control,"POWERING_ON");
148 } else {
149 control_emit_goto_system_state(control,"POWERING_OFF");
150 }
151 } while(0);
152 if (error != GPIO_OK)
Norman James362a80f2015-09-14 14:04:39 -0500153 {
Norman James88872672015-09-21 16:51:35 -0500154 event_log_emit_event_log(event_log, LOG_ALERT, "GPIO set power state error",error);
Norman James362a80f2015-09-14 14:04:39 -0500155 }
Norman James9e6acf92015-09-08 07:00:04 -0500156 }
157 return TRUE;
158}
Norman Jamese2765102015-08-19 22:00:55 -0500159
Norman James9e6acf92015-09-08 07:00:04 -0500160static gboolean
161on_init (Control *control,
162 GDBusMethodInvocation *invocation,
163 gpointer user_data)
164{
Norman James88872672015-09-21 16:51:35 -0500165 pgood_timeout_start = 0;
Norman James9e6acf92015-09-08 07:00:04 -0500166 guint poll_interval = control_get_poll_interval(control);
167 g_timeout_add(poll_interval, poll_pgood, user_data);
168 control_complete_init(control,invocation);
Norman James3f97c5d2015-08-26 17:44:14 -0500169 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500170}
171
172static gboolean
Norman James3f97c5d2015-08-26 17:44:14 -0500173on_get_power_state (ControlPower *pwr,
Norman Jamese2765102015-08-19 22:00:55 -0500174 GDBusMethodInvocation *invocation,
175 gpointer user_data)
176{
Norman James3f97c5d2015-08-26 17:44:14 -0500177 guint pgood = control_power_get_pgood(pwr);
178 control_power_complete_get_power_state(pwr,invocation,pgood);
179 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500180}
181
182static void
183on_bus_acquired (GDBusConnection *connection,
184 const gchar *name,
185 gpointer user_data)
186{
Norman James3f97c5d2015-08-26 17:44:14 -0500187 ObjectSkeleton *object;
Norman James362a80f2015-09-14 14:04:39 -0500188 //g_print ("Acquired a message bus connection: %s\n",name);
Norman James10ff6a32015-08-27 14:24:17 -0500189 cmdline *cmd = user_data;
190 if (cmd->argc < 2)
191 {
192 g_print("No objects created. Put object name(s) on command line\n");
193 return;
194 }
195 manager = g_dbus_object_manager_server_new (dbus_object_path);
Norman James88872672015-09-21 16:51:35 -0500196 gchar *s;
197 s = g_strdup_printf ("%s/%s",dbus_object_path,cmd->argv[1]);
198 g_print("%s\n",s);
199 object = object_skeleton_new (s);
200 g_free (s);
Norman Jamese2765102015-08-19 22:00:55 -0500201
Norman James88872672015-09-21 16:51:35 -0500202 ControlPower* control_power = control_power_skeleton_new ();
203 object_skeleton_set_control_power (object, control_power);
204 g_object_unref (control_power);
205
206 Control* control = control_skeleton_new ();
207 object_skeleton_set_control (object, control);
208 g_object_unref (control);
Norman Jamese2765102015-08-19 22:00:55 -0500209
Norman James88872672015-09-21 16:51:35 -0500210 EventLog* event_log = event_log_skeleton_new ();
211 object_skeleton_set_event_log (object, event_log);
212 g_object_unref (event_log);
Norman Jamesce46e3e2015-08-30 22:25:55 -0500213
Norman James88872672015-09-21 16:51:35 -0500214 //define method callbacks here
215 g_signal_connect (control_power,
216 "handle-set-power-state",
217 G_CALLBACK (on_set_power_state),
218 object); /* user_data */
Norman Jamesce46e3e2015-08-30 22:25:55 -0500219
Norman James88872672015-09-21 16:51:35 -0500220 g_signal_connect (control_power,
221 "handle-get-power-state",
222 G_CALLBACK (on_get_power_state),
223 NULL); /* user_data */
Norman Jamese2765102015-08-19 22:00:55 -0500224
Norman James88872672015-09-21 16:51:35 -0500225 g_signal_connect (control,
226 "handle-init",
227 G_CALLBACK (on_init),
228 object); /* user_data */
Norman James9e6acf92015-09-08 07:00:04 -0500229
230
Norman James88872672015-09-21 16:51:35 -0500231 /* Export the object (@manager takes its own reference to @object) */
232 g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
233 g_object_unref (object);
Norman Jamesce46e3e2015-08-30 22:25:55 -0500234
Norman James3f97c5d2015-08-26 17:44:14 -0500235 /* Export all objects */
236 g_dbus_object_manager_server_set_connection (manager, connection);
237
238 // get gpio device paths
Norman Jamesbd4abd12015-09-16 22:43:46 -0500239 int rc = GPIO_OK;
Norman James32e74e22015-09-15 21:28:06 -0500240 do {
Norman Jamesbd4abd12015-09-16 22:43:46 -0500241
Norman James32e74e22015-09-15 21:28:06 -0500242 rc = gpio_init(connection,&power_pin);
243 if (rc != GPIO_OK) { break; }
244 rc = gpio_init(connection,&pgood);
245 if (rc != GPIO_OK) { break; }
246 rc = gpio_open(&pgood);
Norman James88872672015-09-21 16:51:35 -0500247
Norman James32e74e22015-09-15 21:28:06 -0500248 } while(0);
Norman Jamesbd4abd12015-09-16 22:43:46 -0500249 if (rc != GPIO_OK)
250 {
Norman James88872672015-09-21 16:51:35 -0500251 event_log_emit_event_log(event_log, LOG_ALERT, "GPIO setup error",rc);
Norman Jamesbd4abd12015-09-16 22:43:46 -0500252 }
Norman James88872672015-09-21 16:51:35 -0500253 int rc = gpio_open(&pgood);
254 rc = gpio_read(&pgood,&gpio);
255 gpio_close(&pgood);
256 if (rc == GPIO_OK) {
257 control_power_set_pgood(control_power,gpio);
258
259 } else {
260 }
261
Norman Jamese2765102015-08-19 22:00:55 -0500262}
263
264static void
265on_name_acquired (GDBusConnection *connection,
266 const gchar *name,
267 gpointer user_data)
268{
Norman James362a80f2015-09-14 14:04:39 -0500269 //g_print ("Acquired the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500270}
271
272static void
273on_name_lost (GDBusConnection *connection,
274 const gchar *name,
275 gpointer user_data)
276{
Norman James362a80f2015-09-14 14:04:39 -0500277 //g_print ("Lost the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500278}
279
Norman Jamese2765102015-08-19 22:00:55 -0500280
Norman James3f97c5d2015-08-26 17:44:14 -0500281
282
283/*----------------------------------------------------------------*/
284/* Main Event Loop */
285
Norman Jamese2765102015-08-19 22:00:55 -0500286gint
287main (gint argc, gchar *argv[])
288{
289 GMainLoop *loop;
Norman James90caa3c2015-08-27 21:28:48 -0500290 cmdline cmd;
291 cmd.argc = argc;
292 cmd.argv = argv;
Norman Jamese2765102015-08-19 22:00:55 -0500293
294 guint id;
Norman Jamese2765102015-08-19 22:00:55 -0500295 loop = g_main_loop_new (NULL, FALSE);
296
297 id = g_bus_own_name (G_BUS_TYPE_SESSION,
Norman James26072c02015-08-25 07:14:29 -0500298 dbus_name,
Norman Jamese2765102015-08-19 22:00:55 -0500299 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
300 G_BUS_NAME_OWNER_FLAGS_REPLACE,
301 on_bus_acquired,
302 on_name_acquired,
303 on_name_lost,
Norman James90caa3c2015-08-27 21:28:48 -0500304 &cmd,
Norman Jamese2765102015-08-19 22:00:55 -0500305 NULL);
306
Norman Jamesce46e3e2015-08-30 22:25:55 -0500307 g_main_loop_run (loop);
Norman Jamese2765102015-08-19 22:00:55 -0500308
309 g_bus_unown_name (id);
310 g_main_loop_unref (loop);
311 return 0;
312}