aura  0.1
 All Data Structures Functions Variables Modules Pages
transport-sysfs-gpio.c
1 #include <aura/aura.h>
2 #include <aura/private.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 
8 
9 static int file_get(const char *path, char *dbuf, int dlen)
10 {
11  int ret;
12  int fd = open(path, O_RDONLY);
13  if (-1 == fd) {
14  slog(0, SLOG_ERROR, "sysfsgpio: Failed to open %s for reading", path);
15  return -1;
16  }
17  ret = read(fd, dbuf, dlen);
18  dbuf[ret]=0x0;
19  close(fd);
20  return ret;
21 }
22 
23 static int file_put(const char *path, const char *dbuf)
24 {
25  int ret;
26  int fd = open(path, O_WRONLY);
27  if (-1 == fd) {
28  slog(0, SLOG_ERROR, "sysfsgpio: Failed to open %s for writing", path);
29  return -1;
30  }
31  ret = write(fd, dbuf, strlen(dbuf));
32  close(fd);
33  return ret;
34 }
35 
36 static int gpio_export(int gpio)
37 {
38  char tmp[128];
39  sprintf(tmp, "/sys/class/gpio/gpio%d", gpio);
40  if (0 == access(tmp, F_OK)) {
41  slog(0, SLOG_WARN, "sysfsgpio: GPIO %d already exported", gpio);
42  return 0;
43  }
44 
45  sprintf(tmp, "%d", gpio);
46  if (0 < file_put("/sys/class/gpio/export", tmp))
47  return 0;
48  return -1;
49 }
50 
51 static int check_exported(int gpio)
52 {
53  int ret;
54  char tmp[256];
55  sprintf(tmp, "/sys/class/gpio/gpio%d", gpio);
56  if (0 != access(tmp, F_OK)) {
57  slog(0, SLOG_WARN, "sysfsgpio: GPIO %d not exported, exporting", gpio);
58  if ((ret = gpio_export(gpio)))
59  return ret;
60  }
61  return 0;
62 
63 }
64 
65 static int gpio_write(int gpio, int value)
66 {
67  int ret;
68  char tmp[256];
69 
70  if ((ret = check_exported(gpio)))
71  return ret;
72 
73  sprintf(tmp, "/sys/class/gpio%d/value", gpio);
74  if (0 < file_put(tmp, value ? "1" : "0"))
75  return 0;
76 
77  return -EIO;
78 }
79 
80 static int gpio_read(int gpio, int *value)
81 {
82  int ret;
83  char tmp[256];
84 
85  if ((ret = check_exported(gpio)))
86  return ret;
87 
88  sprintf(tmp, "/sys/class/gpio%d/value", gpio);
89  if (0 < file_get(tmp, tmp, 256))
90  return 0;
91 
92  *value = atoi(tmp);
93 
94  return -EIO;
95 }
96 
97 static int gpio_in(int gpio)
98 {
99  int ret;
100  char tmp[256];
101 
102  if ((ret = check_exported(gpio)))
103  return ret;
104 
105  sprintf(tmp, "/sys/class/gpio%d/direction", gpio);
106  if (0 < file_put(tmp, "in"))
107  return 0;
108 
109  return -EIO;
110 }
111 
112 static int gpio_out(int gpio)
113 {
114  int ret;
115  char tmp[256];
116 
117  if ((ret = check_exported(gpio)))
118  return ret;
119 
120  sprintf(tmp, "/sys/class/gpio%d/direction", gpio);
121  if (0 < file_put(tmp, "out"))
122  return 0;
123 
124  return -EIO;
125 }
126 
127 static int gpio_open(struct aura_node *node, const char *opts)
128 {
129  slog(0, SLOG_INFO, "Opening sysfs/gpio transport");
130  struct aura_export_table *etbl = aura_etable_create(node, 16);
131  if (!etbl)
132  BUG(node, "Failed to create etable");
133  aura_etable_add(etbl, "write", "33", "");
134  aura_etable_add(etbl, "read", "3", "3");
135  aura_etable_add(etbl, "out", "3", "");
136  aura_etable_add(etbl, "in", "3", "");
137  aura_etable_add(etbl, "export", "3", "3");
138  aura_etable_add(etbl, "watch", "3", "");
139  //Change notification
140  aura_etable_add(etbl, "gpio_changed", NULL, "333");
141  aura_etable_activate(etbl);
142  aura_set_status(node, AURA_STATUS_ONLINE);
143  slog(0, SLOG_INFO, "Opened sysfs/gpio transport");
144  return 0;
145 }
146 
147 static void gpio_close(struct aura_node *node)
148 {
149  slog(0, SLOG_INFO, "Closing dummy transport");
150 }
151 
152 #define OPCODE(_name) (strcmp(o->name, _name)==0)
153 
154 static void handle_outbound(struct aura_node *node, struct aura_object *o, struct aura_buffer *buf)
155 {
156  int ret = -EIO;
157  if (OPCODE("export")) {
158  int gpio = aura_buffer_get_u32(buf);
159  slog(4, SLOG_DEBUG, "gpio: export %d", gpio);
160  ret = gpio_export(gpio);
161  } else if (OPCODE("write")) {
162  int gpio = aura_buffer_get_u32(buf);
163  int value = aura_buffer_get_u32(buf);
164  slog(4, SLOG_DEBUG, "gpio: write gpio %d value %d", gpio, value);
165  ret = gpio_write(gpio, value);
166  } else if (OPCODE("in")) {
167  int gpio = aura_buffer_get_u32(buf);
168  ret = gpio_in(gpio);
169  } else if (OPCODE("out")) {
170  int gpio = aura_buffer_get_u32(buf);
171  ret = gpio_out(gpio);
172  } else if (OPCODE("read")) {
173  int gpio = aura_buffer_get_u32(buf);
174  ret = gpio_read(gpio, &gpio);
175  aura_buffer_rewind(buf);
176  aura_buffer_put_u32(buf, gpio);
177  }
178  slog(0, SLOG_DEBUG, "gpio ret = %d", ret);
179  if (ret) {
180  aura_call_fail(node, o);
181  return;
182  }
183  aura_queue_buffer(&node->inbound_buffers, buf);
184 }
185 
186 static void gpio_loop(struct aura_node *node, const struct aura_pollfds *fd)
187 {
188  struct aura_buffer *buf;
189  struct aura_object *o;
190 
191  while(1) {
192  buf = aura_dequeue_buffer(&node->outbound_buffers);
193  if (!buf)
194  break;
195  o = buf->object;
196  handle_outbound(node, o, buf);
197  aura_buffer_release(buf);
198  aura_eventloop_interrupt(aura_eventloop_get_data(node));
199  }
200 }
201 
202 static struct aura_transport gpio = {
203  .name = "gpio",
204  .open = gpio_open,
205  .close = gpio_close,
206  .loop = gpio_loop,
207 };
208 
209 AURA_TRANSPORT(gpio);
void aura_set_status(struct aura_node *node, int status)
Definition: aura.c:808
struct aura_buffer * aura_dequeue_buffer(struct list_head *head)
Definition: queue.c:45
const char * name
Required.
Definition: aura.h:168
struct aura_eventloop * aura_eventloop_get_data(struct aura_node *node)
Definition: aura.c:243
void aura_buffer_put_u32(struct aura_buffer *buf, uint32_t value)
Put an unsigned 32 bit integer to aura buffer.
static void aura_buffer_rewind(struct aura_buffer *buf)
Definition: inlines.h:93
uint32_t aura_buffer_get_u32(struct aura_buffer *buf)
Get an unsigned 32 bit integer from aura buffer.
void(* close)(struct aura_node *node)
Required.
Definition: aura.h:221
void aura_call_fail(struct aura_node *node, struct aura_object *o)
Definition: aura.c:789
int(* open)(struct aura_node *node, const char *opts)
Required.
Definition: aura.h:210
void aura_queue_buffer(struct list_head *list, struct aura_buffer *buf)
Definition: queue.c:16
void aura_buffer_release(struct aura_buffer *buf)
Definition: buffer.c:80
struct aura_object * object
Definition: aura.h:341