xref: /openbmc/skeleton/libopenbmc_intf/gpio.c (revision 40a360c2a4feef97a8f7041e655b2a42e51e0224)
1 #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 <argp.h>
8 #include <sys/stat.h>
9 #include <sys/mman.h>
10 #include "interfaces/openbmc_intf.h"
11 #include "gpio.h"
12 
13 
14 int gpio_writec(GPIO* gpio, char value)
15 {
16 	g_assert (gpio != NULL);
17 	int rc = GPIO_OK;
18 	char buf[1];
19 	buf[0] = value;
20 	if (write(gpio->fd, buf, 1) != 1)
21 	{
22 		rc = GPIO_WRITE_ERROR;
23 	}
24 	return rc;
25 }
26 
27 int gpio_write(GPIO* gpio, uint8_t value)
28 {
29 	g_assert (gpio != NULL);
30 	int rc = GPIO_OK;
31 	char buf[1];
32 	buf[0] = '0';
33 	if (value==1)
34 	{
35 		buf[0]='1';
36 	}
37 	if (write(gpio->fd, buf, 1) != 1)
38 	{
39 		rc = GPIO_WRITE_ERROR;
40 	}
41 	return rc;
42 }
43 
44 int gpio_read(GPIO* gpio, uint8_t *value)
45 {
46 	g_assert (gpio != NULL);
47 	char buf[1];
48 	int r = GPIO_OK;
49 	if (gpio->fd <= 0)
50 	{
51 		r = GPIO_ERROR;
52 	}
53 	else
54 	{
55 		if (read(gpio->fd,&buf,1) != 1)
56 		{
57 			r = GPIO_READ_ERROR;
58 		} else {
59 			if (buf[0]=='1') {
60 				*value = 1;
61 			} else {
62 				*value = 0;
63 			}
64 		}
65 	}
66 	return r;
67 }
68 int gpio_clock_cycle(GPIO* gpio, int num_clks) {
69 	g_assert (gpio != NULL);
70         int i=0;
71 	int r=GPIO_OK;
72         for (i=0;i<num_clks;i++) {
73                 if (gpio_writec(gpio,'0') == -1) {
74 			r = GPIO_WRITE_ERROR;
75 			break;
76 		}
77 		if (gpio_writec(gpio,'1') == -1) {
78 			r = GPIO_WRITE_ERROR;
79 			break;
80 		}
81         }
82 	return r;
83 }
84 
85 // Gets the gpio device path from gpio manager object
86 int gpio_init(GDBusConnection *connection, GPIO* gpio)
87 {
88 	int rc = GPIO_OK;
89 	GDBusProxy *proxy;
90 	GError *error;
91 	GVariant *result;
92 
93 	error = NULL;
94 	g_assert_no_error (error);
95 	error = NULL;
96 	proxy = g_dbus_proxy_new_sync (connection,
97                                  G_DBUS_PROXY_FLAGS_NONE,
98                                  NULL,                      /* GDBusInterfaceInfo */
99                                  "org.openbmc.managers.System", /* name */
100                                  "/org/openbmc/managers/System", /* object path */
101                                  "org.openbmc.managers.System",        /* interface */
102                                  NULL, /* GCancellable */
103                                  &error);
104 	if (error != NULL) {
105 		return GPIO_LOOKUP_ERROR;
106 	}
107 
108 	result = g_dbus_proxy_call_sync (proxy,
109                                    "gpioInit",
110                                    g_variant_new ("(s)", gpio->name),
111                                    G_DBUS_CALL_FLAGS_NONE,
112                                    -1,
113                                    NULL,
114                                    &error);
115 
116 	if (error != NULL) {
117 		return GPIO_LOOKUP_ERROR;
118 	}
119 	g_assert (result != NULL);
120 	g_variant_get (result, "(&si&s)", &gpio->dev,&gpio->num,&gpio->direction);
121 	g_print("GPIO Lookup:  %s = %d,%s\n",gpio->name,gpio->num,gpio->direction);
122 
123 	//export and set direction
124 	char dev[254];
125 	char data[4];
126 	int fd;
127 	do {
128 		struct stat st;
129 
130 		sprintf(dev,"%s/gpio%d/value",gpio->dev,gpio->num);
131 		//check if gpio is exported, if not export
132     		int result = stat(dev, &st);
133     		if (result)
134 		{
135 			sprintf(dev,"%s/export",gpio->dev);
136 			fd = open(dev, O_WRONLY);
137 			if (fd == GPIO_ERROR) {
138 				rc = GPIO_OPEN_ERROR;
139 				break;
140 			}
141 			sprintf(data,"%d",gpio->num);
142 			rc = write(fd,data,strlen(data));
143 			close(fd);
144 			if (rc != strlen(data)) {
145 				rc = GPIO_WRITE_ERROR;
146 				break;
147 			}
148 		}
149 		const char* file = "edge";
150 		if (strcmp(gpio->direction,"in")==0 || strcmp(gpio->direction,"out")==0)
151 		{
152 			file = "direction";
153 		}
154 		sprintf(dev,"%s/gpio%d/%s",gpio->dev,gpio->num,file);
155 		fd = open(dev,O_WRONLY);
156 		if (fd == GPIO_ERROR) {
157 			rc = GPIO_WRITE_ERROR;
158 			break;
159 		}
160 		rc = write(fd,gpio->direction,strlen(gpio->direction));
161 		if (rc != strlen(gpio->direction)) {
162 			rc = GPIO_WRITE_ERROR;
163 			break;
164 		}
165 
166 		close(fd);
167 		rc = GPIO_OK;
168 	} while(0);
169 
170 	return rc;
171 }
172 
173 
174 
175 
176 char* get_gpio_dev(GPIO* gpio)
177 {
178 	char* buf;
179 	sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
180 	return buf;
181 }
182 
183 int gpio_open_interrupt(GPIO* gpio, GIOFunc func, gpointer user_data)
184 {
185 	int rc = GPIO_OK;
186 	char buf[255];
187 	sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
188 	gpio->fd = open(buf, O_RDONLY | O_NONBLOCK );
189 	gpio->irq_inited = false;
190 	if (gpio->fd == -1)
191 	{
192 		rc = GPIO_OPEN_ERROR;
193 	}
194 	else
195 	{
196 		GIOChannel* channel = g_io_channel_unix_new( gpio->fd);
197 		guint id = g_io_add_watch( channel, G_IO_PRI, func, user_data );
198 	}
199 	return rc;
200 }
201 
202 int gpio_open(GPIO* gpio)
203 {
204 	g_assert (gpio != NULL);
205 	// open gpio for writing or reading
206 	char buf[254];
207 	int rc = 0;
208 	gpio->fd = -1;
209 	if (gpio->direction == NULL) {
210 		return GPIO_OPEN_ERROR;
211 	}
212 	if (strcmp(gpio->direction,"in")==0)
213 	{
214 		sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
215 		gpio->fd = open(buf, O_RDONLY);
216 	}
217 	else
218 	{
219 		sprintf(buf, "%s/gpio%d/value", gpio->dev, gpio->num);
220 		gpio->fd = open(buf, O_RDWR);
221 
222 	}
223 	if (gpio->fd == -1) {
224 		return GPIO_OPEN_ERROR;
225 	}
226 	return GPIO_OK;
227 }
228 
229 void gpio_close(GPIO* gpio)
230 {
231 	close(gpio->fd);
232 }
233