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,...
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....
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.