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