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