ApraLinuxUtils 1.0.0
C++ utility library for embedded Linux systems
 
Loading...
Searching...
No Matches
GPIO.cpp
Go to the documentation of this file.
1/*
2 * GPIO.cpp
3 *
4 * Copyright (c) 2024 Apra Labs
5 *
6 * This file is part of ApraUtils.
7 *
8 * Licensed under the MIT License.
9 * See LICENSE file in the project root for full license information.
10 */
11
12#include <stddef.h>
13#include <stdio.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <string.h>
17#include <math.h>
18#include <linux/input.h>
19#include "utils/GPIO.h"
20#include <poll.h>
21
22#define GPIO_TOUT_USEC 100000
23using namespace apra;
24
25GPIO::GPIO(uint gpioNo) :
26 m_fd(-1), m_gpio(gpioNo), m_isRead(false)
27{
28}
29
31{
32}
33
34std::string GPIO::GPIO_EDGES_STR(GPIO_EDGES edge)
35{
36 switch (edge)
37 {
38 case NONE:
39 return "none";
40 case RISING:
41 return "rising";
42 case FALLING:
43 return "falling";
44 case BOTH:
45 return "both";
46 default:
47 break;
48 }
49 return "";
50}
51
52bool GPIO::Init(bool isRead)
53{
54 m_isRead = isRead;
55 if (!Export())
56 {
57 // return false;
58 }
59 return SetDirection(isRead);
60}
61
62bool GPIO::Init4EdgeInterrupt(bool isRead, GPIO_EDGES edge)
63{
64 m_isRead = isRead;
65 if (Init(isRead))
66 {
67 return SetGPIOEdgeEvent(edge);
68 }
69 return false;
70}
71
73{
74 return UnExport();
75}
76
78{
79 char buff[64] = { 0 };
80 snprintf(buff, sizeof(buff), SYS_GPIO_PATH "/gpio%d/value", m_gpio);
81
82 m_fd = open(buff, (m_isRead ? (O_RDONLY | O_NONBLOCK) : O_WRONLY));
83 if (m_fd < 0)
84 {
85 printf("Error opening gpio");
86 return -1;
87 }
88 return m_fd;
89}
90
92{
93 if (m_fd)
94 return close(m_fd);
95 return true;
96}
97
98bool GPIO::Export()
99{
100 int fd, length;
101 char buff[64] = { 0 };
102
103 fd = open(SYS_GPIO_PATH "/export", O_WRONLY);
104 if (fd < 0)
105 {
106 printf("unable to open export for gpio %d\n", m_gpio);
107 return false;
108 }
109
110 length = snprintf(buff, sizeof(buff), "%d", m_gpio);
111 if (write(fd, buff, length) != length)
112 {
113 close(fd);
114 printf("unable to init gpio %d\n", m_gpio);
115 return false;
116 }
117 close(fd);
118 usleep(GPIO_TOUT_USEC);
119 return true;
120}
121
122bool GPIO::UnExport()
123{
124 int fd, length;
125 char buff[64] = { 0 };
126
127 fd = open(SYS_GPIO_PATH "/unexport", O_WRONLY);
128 if (fd < 0)
129 {
130 printf("unable to open gpio %d for unexport\n", m_gpio);
131 return false;
132 }
133
134 length = snprintf(buff, sizeof(buff), "%d", m_gpio);
135 if (write(fd, buff, length) != length)
136 {
137 close(fd);
138 printf("unable to unexport gpio %d\n", m_gpio);
139 return false;
140 }
141 close(fd);
142 return true;
143}
144
145bool GPIO::SetDirection(bool isRead)
146{
147 int fd;
148 char buff[64] = { 0 };
149
150 snprintf(buff, sizeof(buff),
151 SYS_GPIO_PATH "/gpio%d/direction", m_gpio);
152
153 fd = open(buff, O_WRONLY);
154 if (fd < 0)
155 {
156 printf("SetDirection unable to open gpio%d", m_gpio);
157 return false;
158 }
159
160 if (!isRead)
161 {
162 if (write(fd, "out", 4) != 4)
163 {
164 close(fd);
165 printf("unable to make gpio%d as output\n", m_gpio);
166 return false;
167 }
168 }
169 else
170 {
171 if (write(fd, "in", 3) != 3)
172 {
173 close(fd);
174 printf("unable to make gpio%d as input\n", m_gpio);
175 return false;
176 }
177 }
178 close(fd);
179 return true;
180}
181bool GPIO::SetGPIOEdgeEvent(GPIO_EDGES edge)
182{
183 int fd;
184 char buff[64] = { 0 };
185
186 snprintf(buff, sizeof(buff), SYS_GPIO_PATH "/gpio%d/edge", m_gpio);
187
188 fd = open(buff, O_WRONLY);
189 if (fd < 0)
190 {
191 printf("Unable to open gpio%d/edge\n", m_gpio);
192 return false;
193 }
194 std::string edgeStr = GPIO_EDGES_STR(edge);
195 if (write(fd, edgeStr.c_str(), edgeStr.length() + 1)
196 != ((int) (edgeStr.length() + 1)))
197 {
198 printf("Error setting edge to \"%s\"\n", edgeStr.c_str());
199 return false;
200 }
201 close(fd);
202 return true;
203}
204
206{
207 if (!m_fd)
208 {
209 return -1;
210 }
211 char ch;
212 lseek(m_fd, 0, SEEK_SET);
213 if (read(m_fd, &ch, 1) != 1)
214 {
215 printf("Error fetching GPIO value\n");
216 return -1;
217 }
218
219 if (ch != '0')
220 {
221 return 1;
222 }
223 return 0;
224}
225
226bool GPIO::Write(bool makeHigh)
227{
228 if (!m_fd)
229 {
230 return false;
231 }
232 std::string state = makeHigh ? "1" : "0";
233 if (write(m_fd, state.c_str(), 2) != 2)
234 {
235 printf("Error setting GPIO state %s\n", state.c_str());
236 return false;
237 }
238 return true;
239}
240
241int GPIO::ReadOnce(uint gpioNo)
242{
243 GPIO gpio(gpioNo);
244 if (!gpio.Init(true))
245 {
246 return -1;
247 }
248 gpio.Open();
249 int data = gpio.Read();
250 gpio.Close();
251 gpio.UnInit();
252 return data;
253}
254bool GPIO::WriteOnce(uint gpioNo, bool makeHigh)
255{
256 GPIO gpio(gpioNo);
257 if (!gpio.Init(true))
258 {
259 return -1;
260 }
261 gpio.Open();
262 bool response = gpio.Write(makeHigh);
263 gpio.Close();
264 gpio.UnInit();
265 return response;
266}
268{
269 return m_fd;
270}
271
272int GPIO::ReadWithInterrupt(unsigned long uSecTout)
273{
274 struct pollfd fdset;
275 fdset.fd = m_fd;
276 fdset.events = POLLPRI;
277
278 auto rc = poll(&fdset, 1, uSecTout);
279 if (rc < 0)
280 {
281 printf("\npoll() failed!\n");
282 return -1;
283 }
284 else if (rc == 0)
285 {
286 // printf("timeout \n");
287 return -1;
288 }
289
290 if (fdset.revents & POLLPRI)
291 {
292 return Read();
293 }
294
295 return -1;
296}
#define GPIO_TOUT_USEC
Definition GPIO.cpp:22
GPIO_EDGES
Definition GPIO.h:21
@ BOTH
Definition GPIO.h:22
@ NONE
Definition GPIO.h:22
@ FALLING
Definition GPIO.h:22
@ RISING
Definition GPIO.h:22
#define SYS_GPIO_PATH
Definition GPIO.h:18
static int ReadOnce(uint gpioNo)
Definition GPIO.cpp:241
int & GetGPIODescriptor()
Definition GPIO.cpp:267
static bool WriteOnce(uint gpioNo, bool makeHigh)
Definition GPIO.cpp:254
int Open()
Definition GPIO.cpp:77
bool Close()
Definition GPIO.cpp:91
int ReadWithInterrupt(unsigned long uSecTout)
Definition GPIO.cpp:272
GPIO(uint gpioNo)
Definition GPIO.cpp:25
bool UnInit()
Definition GPIO.cpp:72
bool Init(bool isRead)
Definition GPIO.cpp:52
virtual ~GPIO()
Definition GPIO.cpp:30
bool Write(bool makeHigh)
Definition GPIO.cpp:226
int Read()
Definition GPIO.cpp:205
bool Init4EdgeInterrupt(bool isRead, GPIO_EDGES edge)
Definition GPIO.cpp:62