pihwm
A lightweight C library for Raspberry Pi hardware modules.
 All Data Structures Files Functions Groups Pages
pi_gpio.c
Go to the documentation of this file.
1 
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <inttypes.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <poll.h>
36 #include <pthread.h>
37 
38 #include "pihwm.h"
39 #include "pi_gpio.h"
40 
41 static pthread_t isr_handler_thread;
42 static int isr_handler_flag;
43 
44 typedef struct
45 {
46  int pin;
47  void (*isr) (int);
48 } isr_t;
49 
50 
65 static int
66 gpio_edge (int pin, char *edge)
67 {
68  FILE *file;
69  char filename[35];
70 
71  sprintf(filename, "/sys/class/gpio/gpio%d/edge", pin);
72  file = fopen(filename, "w");
73  if ( file == NULL )
74  {
75  debug("[%s] Can't open file (edge): %s\n", __func__, filename);
76  return -1;
77  }
78 
79  fwrite(edge, sizeof (char), strlen (edge) + 1, file);
80 
81  fclose(file);
82 
83  return 1;
84 }
85 
93 static int
94 gpio_valfd (int pin)
95 {
96  int file;
97  char filename[35];
98 
99  sprintf(filename, "/sys/class/gpio/gpio%d/value", pin);
100  file = open(filename, O_RDWR | O_NONBLOCK);
101  if ( file < 0 )
102  {
103  debug("[%s] Can't open file (value): %s\n", __func__, filename);
104  return -1;
105  }
106  else
107  {
108  return file;
109  }
110 
111 }
112 
124 int
125 gpio_init (unsigned int pin, unsigned int dir)
126 {
127  FILE *file;
128  char filename[35], pinStr[2];
129 
130  gpio_release(pin);
131 
132  file = fopen("/sys/class/gpio/export", "w");
133  if ( file == NULL )
134  {
135  debug("[%s] Can't open file (export)\n", __func__);
136  return -1;
137  }
138 
139  sprintf(pinStr, "%d", pin);
140  /* TODO: Add check here */
141  fwrite(pinStr, sizeof (char), strlen (pinStr), file);
142 
143  fclose(file);
144 
145  sprintf(filename, "/sys/class/gpio/gpio%d/direction", pin);
146  file = fopen(filename, "w");
147  if ( file == NULL )
148  {
149  debug("[%s] Can't open file (direction)\n", __func__);
150  return -1;
151  }
152 
153  int ret = 1;
154  if ( dir == 0 )
155  {
156  fwrite("out", sizeof (char), 3, file);
157  }
158  else if ( dir == 1 )
159  {
160  fwrite("in", sizeof (char), 2, file);
161  }
162  else
163  {
164  debug("[%s] Can't set pin direction.\n", __func__);
165  ret = -1;
166  }
167 
168  fclose(file);
169 
170  return ret;
171 }
172 
173 
181 static void *
182 isr_handler (void *isr)
183 {
184  struct pollfd fdset[2];
185  int nfds = 2, gpio_fd, rc;
186  char *buf[64];
187 
188  isr_t i = *(isr_t *) isr;
189 
190  if ( isr_handler_flag )
191  {
192  printf("isr_handler running\n");
193 
194  /* Get /value fd
195  TODO: Add check here */
196  gpio_fd = gpio_valfd((int) i.pin);
197 
198 
199  while ( 1 )
200  {
201  memset((void *) fdset, 0, sizeof (fdset));
202 
203  fdset[0].fd = STDIN_FILENO;
204  fdset[0].events = POLLIN;
205 
206  fdset[1].fd = gpio_fd;
207  fdset[1].events = POLLPRI;
208 
209  rc = poll(fdset, nfds, 1000); /* Timeout in ms */
210 
211  if ( rc < 0 )
212  {
213  debug("\npoll() failed!\n");
214  return (void *) -1;
215  }
216 
217  if ( rc == 0 )
218  {
219  debug("poll() timeout.\n");
220  if ( isr_handler_flag == 0 )
221  {
222  debug("exiting isr_handler (timeout)");
223  pthread_exit(NULL);
224  }
225  }
226 
227  if ( fdset[1].revents & POLLPRI )
228  {
229  /* We have an interrupt! */
230  if ( -1 == read(fdset[1].fd, buf, 64) )
231  {
232  debug("read failed for interrupt");
233  return (void *) -1;
234  }
235 
236  (*i.isr) (i.pin); /* Call the ISR */
237  }
238 
239  if ( fdset[0].revents & POLLIN )
240  {
241  if ( -1 == read(fdset[0].fd, buf, 1) )
242  {
243  debug("read failed for stdin read");
244  return (void *) -1;
245  }
246 
247  printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
248  }
249 
250  fflush(stdout);
251  }
252  }
253  else
254  {
255  debug("exiting isr_handler (flag)");
256  pthread_exit(NULL);
257  }
258 
259 }
260 
274 int
275 gpio_set_int (unsigned int pin, void (*isr) (int), char *mode)
276 {
277  /* Details of the ISR */
278  isr_t *i = (isr_t *) malloc(sizeof (isr_t));
279  i->pin = pin;
280  i->isr = isr;
281 
282  /* Set up interrupt */
283  gpio_edge(pin, mode);
284 
285  /* Set isr_handler flag and create thread
286  TODO: check for errors using retval */
287  isr_handler_flag = 1;
288  pthread_create(&isr_handler_thread, NULL, isr_handler, (void *) i);
289  pthread_tryjoin_np(isr_handler_thread, NULL);
290 
291  return 1;
292 }
293 
303 int
304 gpio_clear_int (unsigned int pin)
305 {
306  /* this will terminate isr_handler thread */
307  isr_handler_flag = 0;
308 
309  /* TODO: Reset "edge", release pin? */
310  return 0; /* Is this a correct return result. */
311 }
312 
321 int
322 gpio_write (unsigned int pin, unsigned int val)
323 {
324  int file;
325  int ret = 1;
326 
327  file = gpio_valfd (pin);
328 
329  if ( val == 0 )
330  {
331  if ( write(file, "0", (sizeof(char) * 1)) == -1 )
332  {
333  debug("[%s] Can't write to GPIO pin", __func__);
334  ret = -1;
335  }
336  }
337  else if ( val == 1 )
338  {
339  if ( write(file, "1", (sizeof(char) * 1)) == -1 )
340  {
341  debug("[%s] Can't write to GPIO pin", __func__);
342  ret = -1;
343  }
344  }
345  else
346  {
347  debug("[%s] Wrong value for the GPIO pin", __func__);
348  ret = -1;
349  }
350 
351  close(file);
352 
353  return ret;
354 }
355 
365 int
366 gpio_read (unsigned int pin)
367 {
368  char valStr[1] = "";
369  unsigned int val;
370  int file;
371 
372  file = gpio_valfd (pin);
373  /* fseek(file, 0, SEEK_SET); */
374  if (read (file, &valStr, 1) == 1)
375  {
376  val = atoi (valStr);
377  debug ("[%s] valStr: %s, val: %d\n", __func__, valStr, val);
378  }
379  else
380  {
381  debug ("[%s] Can't read pin value", __func__);
382  val = -1;
383  }
384 
385  close (file);
386  return val;
387 }
388 
397 int
398 gpio_release (unsigned int pin)
399 {
400  FILE *file;
401  char pinStr[3];
402 
403  file = fopen("/sys/class/gpio/unexport", "w");
404  if ( file == NULL )
405  {
406  debug("[%s] Can't open file (unexport)\n", __func__);
407  return -1;
408  }
409 
410  sprintf(pinStr, "%d", pin);
411  fwrite(pinStr, sizeof (char), strlen (pinStr), file);
412 
413  fclose(file);
414 
415  return 1;
416 }
417