blob: d5fe7ab0e1c6abb9fde7006dfe402ba36435efe0 [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 James362a80f2015-09-14 14:04:39 -050024guint tmp_pgood = 0;
25guint last_pgood = 0;
Norman James32e74e22015-09-15 21:28:06 -050026guint pgood_timeout_count = 0;
Norman James362a80f2015-09-14 14:04:39 -050027
Norman Jamesce46e3e2015-08-30 22:25:55 -050028static gboolean poll_pgood(gpointer user_data)
29{
Norman James8abb50c2015-09-16 10:58:16 -050030 g_print("polling\n");
Norman Jamesce46e3e2015-08-30 22:25:55 -050031 ControlPower *control_power = object_get_control_power((Object*)user_data);
32 Control* control = object_get_control((Object*)user_data);
33 EventLog* event_log = object_get_event_log((Object*)user_data);
34 control_emit_heartbeat(control,dbus_name);
Norman James32e74e22015-09-15 21:28:06 -050035 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
Norman Jamesce46e3e2015-08-30 22:25:55 -050036
Norman James6a1283c2015-09-16 22:21:11 -050037 guint poll_int = control_get_poll_interval(control);
38 if (poll_int == 0)
39 {
40 event_log_emit_event_log(event_log, LOG_ALERT, "Poll interval cannot be 0");
41 return FALSE;
42 }
43 guint pgood_timeout = control_power_get_pgood_timeout(control_power)/poll_int;
Norman James32e74e22015-09-15 21:28:06 -050044
45 if (pgood_timeout_count > pgood_timeout)
46 {
Norman James8abb50c2015-09-16 10:58:16 -050047 event_log_emit_event_log(event_log, LOG_ALERT, "Pgood poll timeout");
Norman James32e74e22015-09-15 21:28:06 -050048 control_power_set_pgood_timeout(control_power,0);
Norman James8abb50c2015-09-16 10:58:16 -050049 pgood_timeout_count = 0;
50 return TRUE;
Norman James32e74e22015-09-15 21:28:06 -050051 }
Norman James362a80f2015-09-14 14:04:39 -050052 //For simulation, remove
53 if (tmp_pgood!=last_pgood) {
54 if (tmp_pgood == 1) {
55 control_emit_goto_system_state(control,"POWERED_ON");
56 } else {
57 control_emit_goto_system_state(control,"POWERED_OFF");
Norman Jamesce46e3e2015-08-30 22:25:55 -050058 }
Norman James362a80f2015-09-14 14:04:39 -050059 }
60
61 last_pgood = tmp_pgood;
Norman James32e74e22015-09-15 21:28:06 -050062 uint8_t gpio;
63 int rc = gpio_read(&pgood,&gpio);
64 if (rc == GPIO_OK)
Norman James362a80f2015-09-14 14:04:39 -050065 {
Norman James32e74e22015-09-15 21:28:06 -050066 //if changed, set property and emit signal
67 if (gpio != control_power_get_pgood(control_power))
68 {
69 control_power_set_pgood(control_power,gpio);
70 if (gpio==0)
71 {
72 control_power_emit_power_lost(control_power);
73 control_emit_goto_system_state(control,"POWERED_OFF");
74 }
75 else
76 {
77 control_power_emit_power_good(control_power);
78 control_emit_goto_system_state(control,"POWERED_ON");
79 }
80 }
81 } else {
Norman James8abb50c2015-09-16 10:58:16 -050082 event_log_emit_event_log(event_log, LOG_ALERT, "GPIO read error");
Norman James6a1283c2015-09-16 22:21:11 -050083 //return FALSE;
Norman James32e74e22015-09-15 21:28:06 -050084 }
85 //pgood is not at desired state yet
86 if (gpio != control_power_get_state(control_power) &&
87 control_power_get_pgood_timeout(control_power) != 0)
88 {
89 pgood_timeout_count++;
90 }
91 else
92 {
93 pgood_timeout_count = 0;
Norman James362a80f2015-09-14 14:04:39 -050094 }
Norman Jamesce46e3e2015-08-30 22:25:55 -050095 return TRUE;
96}
97
98
99
Norman Jamese2765102015-08-19 22:00:55 -0500100static gboolean
Norman James3f97c5d2015-08-26 17:44:14 -0500101on_set_power_state (ControlPower *pwr,
Norman Jamese2765102015-08-19 22:00:55 -0500102 GDBusMethodInvocation *invocation,
103 guint state,
104 gpointer user_data)
105{
Norman James362a80f2015-09-14 14:04:39 -0500106 Control* control = object_get_control((Object*)user_data);
Norman James32e74e22015-09-15 21:28:06 -0500107 EventLog* event_log = object_get_event_log((Object*)user_data);
108 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
Norman James3f97c5d2015-08-26 17:44:14 -0500109 if (state > 1)
110 {
111 g_dbus_method_invocation_return_dbus_error (invocation,
112 "org.openbmc.ControlPower.Error.Failed",
113 "Invalid power state");
114 return TRUE;
115 }
Norman James9e6acf92015-09-08 07:00:04 -0500116 // return from method call
117 control_power_complete_set_power_state(pwr,invocation);
Norman James3f97c5d2015-08-26 17:44:14 -0500118 if (state == control_power_get_state(pwr))
119 {
Norman James9e6acf92015-09-08 07:00:04 -0500120 g_print("Power already at requested state: %d\n",state);
Norman James3f97c5d2015-08-26 17:44:14 -0500121 }
Norman James9e6acf92015-09-08 07:00:04 -0500122 else
123 {
124 g_print("Set power state: %d\n",state);
Norman James362a80f2015-09-14 14:04:39 -0500125 //temporary until real hardware works
126 tmp_pgood = state;
Norman James32e74e22015-09-15 21:28:06 -0500127 int error = 0;
128 do {
129 error = gpio_open(&power_pin);
130 if (error != GPIO_OK) { break; }
131 error = gpio_write(&power_pin,!state);
132 if (error != GPIO_OK) { break; }
133 gpio_close(&power_pin);
134 control_power_set_state(pwr,state);
135 if (state == 1) {
136 control_emit_goto_system_state(control,"POWERING_ON");
137 } else {
138 control_emit_goto_system_state(control,"POWERING_OFF");
139 }
140 } while(0);
141 if (error != GPIO_OK)
Norman James362a80f2015-09-14 14:04:39 -0500142 {
Norman James8abb50c2015-09-16 10:58:16 -0500143 event_log_emit_event_log(event_log, LOG_ALERT, "GPIO setup error");
Norman James362a80f2015-09-14 14:04:39 -0500144 }
Norman James9e6acf92015-09-08 07:00:04 -0500145 }
146 return TRUE;
147}
Norman Jamese2765102015-08-19 22:00:55 -0500148
Norman James9e6acf92015-09-08 07:00:04 -0500149static gboolean
150on_init (Control *control,
151 GDBusMethodInvocation *invocation,
152 gpointer user_data)
153{
154 guint poll_interval = control_get_poll_interval(control);
155 g_timeout_add(poll_interval, poll_pgood, user_data);
156 control_complete_init(control,invocation);
Norman James3f97c5d2015-08-26 17:44:14 -0500157 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500158}
159
160static gboolean
Norman James3f97c5d2015-08-26 17:44:14 -0500161on_get_power_state (ControlPower *pwr,
Norman Jamese2765102015-08-19 22:00:55 -0500162 GDBusMethodInvocation *invocation,
163 gpointer user_data)
164{
Norman James3f97c5d2015-08-26 17:44:14 -0500165 guint pgood = control_power_get_pgood(pwr);
166 control_power_complete_get_power_state(pwr,invocation,pgood);
167 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500168}
169
170static void
171on_bus_acquired (GDBusConnection *connection,
172 const gchar *name,
173 gpointer user_data)
174{
Norman James3f97c5d2015-08-26 17:44:14 -0500175 ObjectSkeleton *object;
Norman James362a80f2015-09-14 14:04:39 -0500176 //g_print ("Acquired a message bus connection: %s\n",name);
Norman James10ff6a32015-08-27 14:24:17 -0500177 cmdline *cmd = user_data;
178 if (cmd->argc < 2)
179 {
180 g_print("No objects created. Put object name(s) on command line\n");
181 return;
182 }
183 manager = g_dbus_object_manager_server_new (dbus_object_path);
184 int i=0;
185 for (i=1;i<cmd->argc;i++)
186 {
187 gchar *s;
188 s = g_strdup_printf ("%s/%s",dbus_object_path,cmd->argv[i]);
Norman James362a80f2015-09-14 14:04:39 -0500189 g_print("%s\n",s);
Norman James10ff6a32015-08-27 14:24:17 -0500190 object = object_skeleton_new (s);
191 g_free (s);
Norman Jamese2765102015-08-19 22:00:55 -0500192
Norman James10ff6a32015-08-27 14:24:17 -0500193 ControlPower* control_power = control_power_skeleton_new ();
194 object_skeleton_set_control_power (object, control_power);
195 g_object_unref (control_power);
Norman Jamese2765102015-08-19 22:00:55 -0500196
Norman Jamesce46e3e2015-08-30 22:25:55 -0500197 Control* control = control_skeleton_new ();
198 object_skeleton_set_control (object, control);
199 g_object_unref (control);
200
201 EventLog* event_log = event_log_skeleton_new ();
202 object_skeleton_set_event_log (object, event_log);
203 g_object_unref (event_log);
204
Norman James10ff6a32015-08-27 14:24:17 -0500205 //define method callbacks here
206 g_signal_connect (control_power,
207 "handle-set-power-state",
208 G_CALLBACK (on_set_power_state),
Norman James362a80f2015-09-14 14:04:39 -0500209 object); /* user_data */
Norman Jamese2765102015-08-19 22:00:55 -0500210
Norman James10ff6a32015-08-27 14:24:17 -0500211 g_signal_connect (control_power,
212 "handle-get-power-state",
213 G_CALLBACK (on_get_power_state),
214 NULL); /* user_data */
Norman Jamese2765102015-08-19 22:00:55 -0500215
Norman James9e6acf92015-09-08 07:00:04 -0500216 g_signal_connect (control,
217 "handle-init",
218 G_CALLBACK (on_init),
219 object); /* user_data */
220
221
Norman Jamesce46e3e2015-08-30 22:25:55 -0500222
Norman James10ff6a32015-08-27 14:24:17 -0500223 /* Export the object (@manager takes its own reference to @object) */
224 g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
225 g_object_unref (object);
226 }
Norman James3f97c5d2015-08-26 17:44:14 -0500227 /* Export all objects */
228 g_dbus_object_manager_server_set_connection (manager, connection);
229
230 // get gpio device paths
Norman James32e74e22015-09-15 21:28:06 -0500231 do {
232 int rc = GPIO_OK;
233 rc = gpio_init(connection,&power_pin);
234 if (rc != GPIO_OK) { break; }
235 rc = gpio_init(connection,&pgood);
236 if (rc != GPIO_OK) { break; }
237 rc = gpio_open(&pgood);
238 if (rc != GPIO_OK) { break; }
239 } while(0);
Norman Jamese2765102015-08-19 22:00:55 -0500240}
241
242static void
243on_name_acquired (GDBusConnection *connection,
244 const gchar *name,
245 gpointer user_data)
246{
Norman James362a80f2015-09-14 14:04:39 -0500247 //g_print ("Acquired the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500248}
249
250static void
251on_name_lost (GDBusConnection *connection,
252 const gchar *name,
253 gpointer user_data)
254{
Norman James362a80f2015-09-14 14:04:39 -0500255 //g_print ("Lost the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500256}
257
Norman Jamese2765102015-08-19 22:00:55 -0500258
Norman James3f97c5d2015-08-26 17:44:14 -0500259
260
261/*----------------------------------------------------------------*/
262/* Main Event Loop */
263
Norman Jamese2765102015-08-19 22:00:55 -0500264gint
265main (gint argc, gchar *argv[])
266{
267 GMainLoop *loop;
Norman James90caa3c2015-08-27 21:28:48 -0500268 cmdline cmd;
269 cmd.argc = argc;
270 cmd.argv = argv;
Norman Jamese2765102015-08-19 22:00:55 -0500271
272 guint id;
Norman Jamese2765102015-08-19 22:00:55 -0500273 loop = g_main_loop_new (NULL, FALSE);
274
275 id = g_bus_own_name (G_BUS_TYPE_SESSION,
Norman James26072c02015-08-25 07:14:29 -0500276 dbus_name,
Norman Jamese2765102015-08-19 22:00:55 -0500277 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
278 G_BUS_NAME_OWNER_FLAGS_REPLACE,
279 on_bus_acquired,
280 on_name_acquired,
281 on_name_lost,
Norman James90caa3c2015-08-27 21:28:48 -0500282 &cmd,
Norman Jamese2765102015-08-19 22:00:55 -0500283 NULL);
284
Norman Jamesce46e3e2015-08-30 22:25:55 -0500285 g_main_loop_run (loop);
Norman Jamese2765102015-08-19 22:00:55 -0500286
287 g_bus_unown_name (id);
288 g_main_loop_unref (loop);
289 return 0;
290}