blob: 33955027d3ca5ce27e4e9dbed888053d9a544c4b [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 James362a80f2015-09-14 14:04:39 -05009#include "interfaces/openbmc_intf.h"
Norman James10ff6a32015-08-27 14:24:17 -050010#include "openbmc.h"
11#include "gpio.h"
Norman James32e74e22015-09-15 21:28:06 -050012#include "event_log.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{
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);
33 control_emit_heartbeat(control,dbus_name);
Norman James32e74e22015-09-15 21:28:06 -050034 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
Norman Jamesce46e3e2015-08-30 22:25:55 -050035
Norman James32e74e22015-09-15 21:28:06 -050036 guint pgood_timeout = control_power_get_pgood_timeout(control_power)/
37 control_get_poll_interval(control);
38
39 if (pgood_timeout_count > pgood_timeout)
40 {
41 event_log_emit_event_log(event_log, FATAL, "Pgood poll timeout");
42 control_power_set_pgood_timeout(control_power,0);
43 //return FALSE;
44 }
Norman James362a80f2015-09-14 14:04:39 -050045 //For simulation, remove
46 if (tmp_pgood!=last_pgood) {
47 if (tmp_pgood == 1) {
48 control_emit_goto_system_state(control,"POWERED_ON");
49 } else {
50 control_emit_goto_system_state(control,"POWERED_OFF");
Norman Jamesce46e3e2015-08-30 22:25:55 -050051 }
Norman James362a80f2015-09-14 14:04:39 -050052 }
53
54 last_pgood = tmp_pgood;
Norman James32e74e22015-09-15 21:28:06 -050055 uint8_t gpio;
56 int rc = gpio_read(&pgood,&gpio);
57 if (rc == GPIO_OK)
Norman James362a80f2015-09-14 14:04:39 -050058 {
Norman James32e74e22015-09-15 21:28:06 -050059 //if changed, set property and emit signal
60 if (gpio != control_power_get_pgood(control_power))
61 {
62 control_power_set_pgood(control_power,gpio);
63 if (gpio==0)
64 {
65 control_power_emit_power_lost(control_power);
66 control_emit_goto_system_state(control,"POWERED_OFF");
67 }
68 else
69 {
70 control_power_emit_power_good(control_power);
71 control_emit_goto_system_state(control,"POWERED_ON");
72 }
73 }
74 } else {
75 event_log_emit_event_log(event_log, FATAL, "GPIO read error");
76 //return FALSE;
77 }
78 //pgood is not at desired state yet
79 if (gpio != control_power_get_state(control_power) &&
80 control_power_get_pgood_timeout(control_power) != 0)
81 {
82 pgood_timeout_count++;
83 }
84 else
85 {
86 pgood_timeout_count = 0;
Norman James362a80f2015-09-14 14:04:39 -050087 }
Norman Jamesce46e3e2015-08-30 22:25:55 -050088 return TRUE;
89}
90
91
92
Norman Jamese2765102015-08-19 22:00:55 -050093static gboolean
Norman James3f97c5d2015-08-26 17:44:14 -050094on_set_power_state (ControlPower *pwr,
Norman Jamese2765102015-08-19 22:00:55 -050095 GDBusMethodInvocation *invocation,
96 guint state,
97 gpointer user_data)
98{
Norman James362a80f2015-09-14 14:04:39 -050099 Control* control = object_get_control((Object*)user_data);
Norman James32e74e22015-09-15 21:28:06 -0500100 EventLog* event_log = object_get_event_log((Object*)user_data);
101 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
Norman James3f97c5d2015-08-26 17:44:14 -0500102 if (state > 1)
103 {
104 g_dbus_method_invocation_return_dbus_error (invocation,
105 "org.openbmc.ControlPower.Error.Failed",
106 "Invalid power state");
107 return TRUE;
108 }
Norman James9e6acf92015-09-08 07:00:04 -0500109 // return from method call
110 control_power_complete_set_power_state(pwr,invocation);
Norman James3f97c5d2015-08-26 17:44:14 -0500111 if (state == control_power_get_state(pwr))
112 {
Norman James9e6acf92015-09-08 07:00:04 -0500113 g_print("Power already at requested state: %d\n",state);
Norman James3f97c5d2015-08-26 17:44:14 -0500114 }
Norman James9e6acf92015-09-08 07:00:04 -0500115 else
116 {
117 g_print("Set power state: %d\n",state);
Norman James362a80f2015-09-14 14:04:39 -0500118 //temporary until real hardware works
119 tmp_pgood = state;
Norman James32e74e22015-09-15 21:28:06 -0500120 int error = 0;
121 do {
122 error = gpio_open(&power_pin);
123 if (error != GPIO_OK) { break; }
124 error = gpio_write(&power_pin,!state);
125 if (error != GPIO_OK) { break; }
126 gpio_close(&power_pin);
127 control_power_set_state(pwr,state);
128 if (state == 1) {
129 control_emit_goto_system_state(control,"POWERING_ON");
130 } else {
131 control_emit_goto_system_state(control,"POWERING_OFF");
132 }
133 } while(0);
134 if (error != GPIO_OK)
Norman James362a80f2015-09-14 14:04:39 -0500135 {
Norman James32e74e22015-09-15 21:28:06 -0500136 event_log_emit_event_log(event_log, FATAL, "GPIO setup error");
Norman James362a80f2015-09-14 14:04:39 -0500137 }
Norman James9e6acf92015-09-08 07:00:04 -0500138 }
139 return TRUE;
140}
Norman Jamese2765102015-08-19 22:00:55 -0500141
Norman James9e6acf92015-09-08 07:00:04 -0500142static gboolean
143on_init (Control *control,
144 GDBusMethodInvocation *invocation,
145 gpointer user_data)
146{
147 guint poll_interval = control_get_poll_interval(control);
148 g_timeout_add(poll_interval, poll_pgood, user_data);
149 control_complete_init(control,invocation);
Norman James3f97c5d2015-08-26 17:44:14 -0500150 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500151}
152
153static gboolean
Norman James3f97c5d2015-08-26 17:44:14 -0500154on_get_power_state (ControlPower *pwr,
Norman Jamese2765102015-08-19 22:00:55 -0500155 GDBusMethodInvocation *invocation,
156 gpointer user_data)
157{
Norman James3f97c5d2015-08-26 17:44:14 -0500158 guint pgood = control_power_get_pgood(pwr);
159 control_power_complete_get_power_state(pwr,invocation,pgood);
160 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500161}
162
163static void
164on_bus_acquired (GDBusConnection *connection,
165 const gchar *name,
166 gpointer user_data)
167{
Norman James3f97c5d2015-08-26 17:44:14 -0500168 ObjectSkeleton *object;
Norman James362a80f2015-09-14 14:04:39 -0500169 //g_print ("Acquired a message bus connection: %s\n",name);
Norman James10ff6a32015-08-27 14:24:17 -0500170 cmdline *cmd = user_data;
171 if (cmd->argc < 2)
172 {
173 g_print("No objects created. Put object name(s) on command line\n");
174 return;
175 }
176 manager = g_dbus_object_manager_server_new (dbus_object_path);
177 int i=0;
178 for (i=1;i<cmd->argc;i++)
179 {
180 gchar *s;
181 s = g_strdup_printf ("%s/%s",dbus_object_path,cmd->argv[i]);
Norman James362a80f2015-09-14 14:04:39 -0500182 g_print("%s\n",s);
Norman James10ff6a32015-08-27 14:24:17 -0500183 object = object_skeleton_new (s);
184 g_free (s);
Norman Jamese2765102015-08-19 22:00:55 -0500185
Norman James10ff6a32015-08-27 14:24:17 -0500186 ControlPower* control_power = control_power_skeleton_new ();
187 object_skeleton_set_control_power (object, control_power);
188 g_object_unref (control_power);
Norman Jamese2765102015-08-19 22:00:55 -0500189
Norman Jamesce46e3e2015-08-30 22:25:55 -0500190 Control* control = control_skeleton_new ();
191 object_skeleton_set_control (object, control);
192 g_object_unref (control);
193
194 EventLog* event_log = event_log_skeleton_new ();
195 object_skeleton_set_event_log (object, event_log);
196 g_object_unref (event_log);
197
Norman James10ff6a32015-08-27 14:24:17 -0500198 //define method callbacks here
199 g_signal_connect (control_power,
200 "handle-set-power-state",
201 G_CALLBACK (on_set_power_state),
Norman James362a80f2015-09-14 14:04:39 -0500202 object); /* user_data */
Norman Jamese2765102015-08-19 22:00:55 -0500203
Norman James10ff6a32015-08-27 14:24:17 -0500204 g_signal_connect (control_power,
205 "handle-get-power-state",
206 G_CALLBACK (on_get_power_state),
207 NULL); /* user_data */
Norman Jamese2765102015-08-19 22:00:55 -0500208
Norman James9e6acf92015-09-08 07:00:04 -0500209 g_signal_connect (control,
210 "handle-init",
211 G_CALLBACK (on_init),
212 object); /* user_data */
213
214
Norman Jamesce46e3e2015-08-30 22:25:55 -0500215
Norman James10ff6a32015-08-27 14:24:17 -0500216 /* Export the object (@manager takes its own reference to @object) */
217 g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
218 g_object_unref (object);
219 }
Norman James3f97c5d2015-08-26 17:44:14 -0500220 /* Export all objects */
221 g_dbus_object_manager_server_set_connection (manager, connection);
222
223 // get gpio device paths
Norman James32e74e22015-09-15 21:28:06 -0500224 do {
225 int rc = GPIO_OK;
226 rc = gpio_init(connection,&power_pin);
227 if (rc != GPIO_OK) { break; }
228 rc = gpio_init(connection,&pgood);
229 if (rc != GPIO_OK) { break; }
230 rc = gpio_open(&pgood);
231 if (rc != GPIO_OK) { break; }
232 } while(0);
Norman Jamese2765102015-08-19 22:00:55 -0500233}
234
235static void
236on_name_acquired (GDBusConnection *connection,
237 const gchar *name,
238 gpointer user_data)
239{
Norman James362a80f2015-09-14 14:04:39 -0500240 //g_print ("Acquired the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500241}
242
243static void
244on_name_lost (GDBusConnection *connection,
245 const gchar *name,
246 gpointer user_data)
247{
Norman James362a80f2015-09-14 14:04:39 -0500248 //g_print ("Lost the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500249}
250
Norman Jamese2765102015-08-19 22:00:55 -0500251
Norman James3f97c5d2015-08-26 17:44:14 -0500252
253
254/*----------------------------------------------------------------*/
255/* Main Event Loop */
256
Norman Jamese2765102015-08-19 22:00:55 -0500257gint
258main (gint argc, gchar *argv[])
259{
260 GMainLoop *loop;
Norman James90caa3c2015-08-27 21:28:48 -0500261 cmdline cmd;
262 cmd.argc = argc;
263 cmd.argv = argv;
Norman Jamese2765102015-08-19 22:00:55 -0500264
265 guint id;
Norman Jamese2765102015-08-19 22:00:55 -0500266 loop = g_main_loop_new (NULL, FALSE);
267
268 id = g_bus_own_name (G_BUS_TYPE_SESSION,
Norman James26072c02015-08-25 07:14:29 -0500269 dbus_name,
Norman Jamese2765102015-08-19 22:00:55 -0500270 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
271 G_BUS_NAME_OWNER_FLAGS_REPLACE,
272 on_bus_acquired,
273 on_name_acquired,
274 on_name_lost,
Norman James90caa3c2015-08-27 21:28:48 -0500275 &cmd,
Norman Jamese2765102015-08-19 22:00:55 -0500276 NULL);
277
Norman Jamesce46e3e2015-08-30 22:25:55 -0500278 g_main_loop_run (loop);
Norman Jamese2765102015-08-19 22:00:55 -0500279
280 g_bus_unown_name (id);
281 g_main_loop_unref (loop);
282 return 0;
283}