pihwm  r1
A lightweight C library for Raspberry Pi hardware modules.
 All Data Structures Files Functions Modules 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  debug("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  debug("\npoll() stdin read 0x%2.2X\n", 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 
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:125
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:398
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:322
int gpio_read(unsigned int pin)
Read the value on the pin numbered pin on the Raspberry Pi P1 header.
Definition: pi_gpio.c:366
gpio library headers
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:275
Definition: pi_gpio.c:44
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:304
Header for general library functionality.