Skip to content

Commit 9fdf1a2

Browse files
committed
Refactor GPIO library
Signed-off-by: Roman Ondráček <[email protected]>
1 parent b46f3d3 commit 9fdf1a2

File tree

5 files changed

+413
-383
lines changed

5 files changed

+413
-383
lines changed

include/iqrf_debug.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#ifdef NDEBUG
4+
#ifndef IQRF_DEBUG_PRINT
5+
#define IQRF_DEBUG_PRINT(fmt, ...)
6+
#endif
7+
#ifndef IQRF_DEBUG_PRINTF
8+
#define IQRF_DEBUG_PRINTF(fmt, ...)
9+
#endif
10+
#else
11+
#ifndef IQRF_DEBUG_PRINT
12+
#define IQRF_DEBUG_PRINT(str) do { \
13+
fprintf(stderr, "%s:%d - %s(): " str "\n", __FILE__, __LINE__, __func__); \
14+
} while (0)
15+
#endif
16+
#ifndef IQRF_DEBUG_PRINTF
17+
#define IQRF_DEBUG_PRINTF(fmt, ...) do { \
18+
fprintf(stderr, "%s:%d - %s(): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__); \
19+
} while (0)
20+
#endif
21+
#endif

include/iqrf_gpio.h

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#ifndef IQRF_GPIO_H
2+
#define IQRF_GPIO_H
3+
4+
#include <errno.h>
5+
#include <inttypes.h>
6+
#include <stdbool.h>
7+
#include <stdio.h>
8+
#include <stdint.h>
9+
#include <string.h>
10+
11+
#ifndef WIN32
12+
#include <fcntl.h>
13+
#include <unistd.h>
14+
#endif
15+
16+
#include "iqrf_debug.h"
17+
#include "sleepWrapper.h"
18+
19+
#define IQRF_GPIO_SYSFS_BASE_PATH "/sys/class/gpio/"
20+
#define IQRF_GPIO_SYSFS_BUFFER_SIZE 64
21+
#define IQRF_GPIO_DIRECTION_BUFFER_SIZE 4
22+
#define IQRF_GPIO_PIN_BUFFER_SIZE 20
23+
#define IQRF_GPIO_VALUE_BUFFER_SIZE 2
24+
25+
static const int64_t IQRF_GPIO_PIN_UNKNOWN = -1;
26+
27+
typedef enum {
28+
IQRF_GPIO_ACTION_DIRECTION,
29+
IQRF_GPIO_ACTION_VALUE,
30+
} iqrf_gpio_action_t;
31+
32+
typedef enum {
33+
IQRF_GPIO_DIRECTION_UNKNOWN = -1,
34+
IQRF_GPIO_DIRECTION_IN,
35+
IQRF_GPIO_DIRECTION_OUT,
36+
} iqrf_gpio_direction_t;
37+
38+
typedef enum {
39+
IQRF_GPIO_ERROR_OK,
40+
IQRF_GPIO_ERROR_INVALID_PIN,
41+
IQRF_GPIO_ERROR_OPEN_FAILED,
42+
IQRF_GPIO_ERROR_WRITE_FAILED,
43+
IQRF_GPIO_ERROR_NULL_POINTER,
44+
} iqrf_gpio_error_t;
45+
46+
/**
47+
* Exports the GPIO pin
48+
* @param pin GPIO pin to export
49+
* @return Execution status
50+
*/
51+
iqrf_gpio_error_t iqrf_gpio_export(int64_t pin);
52+
53+
/**
54+
* Unexports the GPIO pin
55+
* @param pin GPIO pin to unexport
56+
* @return Execution status
57+
*/
58+
iqrf_gpio_error_t iqrf_gpio_unexport(int64_t pin);
59+
60+
/**
61+
* Retrieves the direction for GPIO pin
62+
* @param pin GPIO pin
63+
* @param direction GPIO pin direction
64+
* @return Execution status
65+
*/
66+
iqrf_gpio_error_t iqrf_gpio_get_direction(int64_t pin, iqrf_gpio_direction_t *direction);
67+
68+
/**
69+
* Sets the direction for GPIO pin
70+
* @param pin GPIO pin
71+
* @param direction GPIO pin direction
72+
* @return Execution status
73+
*/
74+
iqrf_gpio_error_t iqrf_gpio_set_direction(int64_t pin, iqrf_gpio_direction_t direction);
75+
76+
/**
77+
* Retrieves the direction for GPIO pin
78+
* @param pin GPIO pin
79+
* @param value GPIO pin output value
80+
* @return Execution status
81+
*/
82+
iqrf_gpio_error_t iqrf_gpio_get_value(int64_t pin, bool *value);
83+
84+
/**
85+
* Sets the direction for GPIO pin
86+
* @param pin GPIO pin
87+
* @param value GPIO pin output value
88+
* @return Execution status
89+
*/
90+
iqrf_gpio_error_t iqrf_gpio_set_value(int64_t pin, bool value);
91+
92+
/**
93+
* Creates sysfs path
94+
* @param pin GPIO pin
95+
* @param action GPIO action
96+
* @param targetPath
97+
*/
98+
void iqrf_gpio_create_sysfs_path(int64_t pin, iqrf_gpio_action_t action, char *targetPath);
99+
100+
/**
101+
* Initializes a GPIO pin
102+
* @param pin GPIO pin number
103+
* @param direction GPIO pin direction
104+
* @param initialValue Initial output value
105+
* @return Execution status
106+
*/
107+
iqrf_gpio_error_t iqrf_gpio_init(int64_t pin, iqrf_gpio_direction_t direction, bool initialValue);
108+
109+
/**
110+
* Initializes a GPIO pin as an input
111+
* @param pin GPIO pin number
112+
* @return Execution status
113+
*/
114+
iqrf_gpio_error_t iqrf_gpio_init_input(int64_t pin);
115+
116+
/**
117+
* Initializes a GPIO pin as an output
118+
* @param pin GPIO pin
119+
* @param initialValue Initial output value
120+
* @return Execution status
121+
*/
122+
iqrf_gpio_error_t iqrf_gpio_init_output(int64_t pin, bool initialValue);
123+
124+
#endif

spi_iqrf/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
project(spi_iqrf)
22

3-
set(_SRC_FILES
4-
spi_iqrf.c
5-
)
3+
set(_SRC_FILES iqrf_gpio.c spi_iqrf.c)
64

75
add_library(${PROJECT_NAME} STATIC ${_SRC_FILES})

spi_iqrf/iqrf_gpio.c

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#include "iqrf_gpio.h"
2+
3+
#ifdef WIN32
4+
#define snprintf _snprintf
5+
#endif
6+
7+
static const char* IQRF_GPIO_ACTION_DIRECTION_STR = "direction";
8+
static const char* IQRF_GPIO_ACTION_VALUE_STR = "value";
9+
static const char* IQRF_GPIO_DIRECTION_IN_STR = "in";
10+
static const char* IQRF_GPIO_DIRECTION_OUT_STR = "out";
11+
12+
void iqrf_gpio_create_sysfs_path(int64_t pin, iqrf_gpio_action_t action, char *targetPath) {
13+
const char *actionString = action == IQRF_GPIO_ACTION_DIRECTION ? IQRF_GPIO_ACTION_DIRECTION_STR : IQRF_GPIO_ACTION_VALUE_STR;
14+
snprintf(targetPath, IQRF_GPIO_SYSFS_BUFFER_SIZE, IQRF_GPIO_SYSFS_BASE_PATH"gpio%"PRId64"/%s", pin, actionString);
15+
}
16+
17+
iqrf_gpio_error_t iqrf_gpio_export(int64_t pin) {
18+
#ifdef WIN32
19+
return IQRF_GPIO_ERROR_OK;
20+
#else
21+
if (pin < 0) {
22+
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
23+
return IQRF_GPIO_ERROR_INVALID_PIN;
24+
}
25+
char *path = IQRF_GPIO_SYSFS_BASE_PATH"export";
26+
int fd = open(path, O_WRONLY);
27+
if (fd == -1) {
28+
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
29+
return IQRF_GPIO_ERROR_OPEN_FAILED;
30+
}
31+
char buffer[IQRF_GPIO_PIN_BUFFER_SIZE] = "";
32+
snprintf(buffer, IQRF_GPIO_PIN_BUFFER_SIZE, "%"PRId64, pin);
33+
ssize_t writtenSize = write(fd, buffer, IQRF_GPIO_PIN_BUFFER_SIZE);
34+
if (writtenSize == -1) {
35+
close(fd);
36+
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
37+
return IQRF_GPIO_ERROR_WRITE_FAILED;
38+
}
39+
close(fd);
40+
return IQRF_GPIO_ERROR_OK;
41+
#endif
42+
}
43+
44+
iqrf_gpio_error_t iqrf_gpio_unexport(int64_t pin) {
45+
#ifdef WIN32
46+
return IQRF_GPIO_ERROR_OK;
47+
#else
48+
if (pin < 0) {
49+
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
50+
return IQRF_GPIO_ERROR_INVALID_PIN;
51+
}
52+
char *path = IQRF_GPIO_SYSFS_BASE_PATH"unexport";
53+
int fd = open(path, O_WRONLY);
54+
if (fd == -1) {
55+
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
56+
return IQRF_GPIO_ERROR_OPEN_FAILED;
57+
}
58+
char buffer[IQRF_GPIO_PIN_BUFFER_SIZE] = "";
59+
snprintf(buffer, IQRF_GPIO_PIN_BUFFER_SIZE, "%"PRId64, pin);
60+
ssize_t writtenSize = write(fd, buffer, IQRF_GPIO_PIN_BUFFER_SIZE);
61+
if (writtenSize == -1) {
62+
close(fd);
63+
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
64+
return IQRF_GPIO_ERROR_WRITE_FAILED;
65+
}
66+
close(fd);
67+
return IQRF_GPIO_ERROR_OK;
68+
#endif
69+
}
70+
71+
iqrf_gpio_error_t iqrf_gpio_get_direction(int64_t pin, iqrf_gpio_direction_t *direction) {
72+
#ifdef WIN32
73+
return IQRF_GPIO_ERROR_OK;
74+
#else
75+
if (direction == NULL) {
76+
return IQRF_GPIO_ERROR_NULL_POINTER;
77+
}
78+
if (pin < 0) {
79+
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
80+
return IQRF_GPIO_ERROR_INVALID_PIN;
81+
}
82+
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
83+
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_DIRECTION, path);
84+
int fd = open(path, O_RDONLY);
85+
if (fd == -1) {
86+
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
87+
return IQRF_GPIO_ERROR_OPEN_FAILED;
88+
}
89+
char buffer[IQRF_GPIO_DIRECTION_BUFFER_SIZE] = "";
90+
ssize_t readSize = read(fd, buffer, IQRF_GPIO_DIRECTION_BUFFER_SIZE);
91+
if (readSize == -1) {
92+
close(fd);
93+
IQRF_DEBUG_PRINTF("Unable to read from %s", path);
94+
return IQRF_GPIO_ERROR_WRITE_FAILED;
95+
}
96+
if (strncmp(buffer, IQRF_GPIO_DIRECTION_IN_STR, IQRF_GPIO_DIRECTION_BUFFER_SIZE - 1) == 0) {
97+
*direction = IQRF_GPIO_DIRECTION_IN;
98+
} else if (strncmp(buffer, IQRF_GPIO_DIRECTION_OUT_STR, IQRF_GPIO_DIRECTION_BUFFER_SIZE - 1) == 0) {
99+
*direction = IQRF_GPIO_DIRECTION_OUT;
100+
} else {
101+
*direction = IQRF_GPIO_DIRECTION_UNKNOWN;
102+
}
103+
close(fd);
104+
return IQRF_GPIO_ERROR_OK;
105+
#endif
106+
}
107+
108+
iqrf_gpio_error_t iqrf_gpio_set_direction(int64_t pin, iqrf_gpio_direction_t direction) {
109+
#ifdef WIN32
110+
return IQRF_GPIO_ERROR_OK;
111+
#else
112+
if (pin < 0) {
113+
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
114+
return IQRF_GPIO_ERROR_INVALID_PIN;
115+
}
116+
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
117+
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_DIRECTION, path);
118+
int fd = open(path, O_WRONLY);
119+
if (fd == -1) {
120+
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
121+
return IQRF_GPIO_ERROR_OPEN_FAILED;
122+
}
123+
const char *buffer = direction == IQRF_GPIO_DIRECTION_IN ? IQRF_GPIO_DIRECTION_IN_STR : IQRF_GPIO_DIRECTION_OUT_STR;
124+
ssize_t writtenSize = write(fd, buffer, strlen(buffer));
125+
if (writtenSize == -1) {
126+
close(fd);
127+
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
128+
return IQRF_GPIO_ERROR_WRITE_FAILED;
129+
}
130+
close(fd);
131+
return IQRF_GPIO_ERROR_OK;
132+
#endif
133+
}
134+
135+
iqrf_gpio_error_t iqrf_gpio_get_value(int64_t pin, bool *value) {
136+
#ifdef WIN32
137+
return IQRF_GPIO_ERROR_OK;
138+
#else
139+
if (value == NULL) {
140+
return IQRF_GPIO_ERROR_NULL_POINTER;
141+
}
142+
if (pin < 0) {
143+
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
144+
return IQRF_GPIO_ERROR_INVALID_PIN;
145+
}
146+
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
147+
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_VALUE, path);
148+
int fd = open(path, O_RDONLY);
149+
if (fd == -1) {
150+
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
151+
return IQRF_GPIO_ERROR_OPEN_FAILED;
152+
}
153+
char buffer[IQRF_GPIO_VALUE_BUFFER_SIZE] = "";
154+
ssize_t readSize = read(fd, buffer, IQRF_GPIO_VALUE_BUFFER_SIZE);
155+
if (readSize == -1) {
156+
close(fd);
157+
IQRF_DEBUG_PRINTF("Unable to read from %s", path);
158+
return IQRF_GPIO_ERROR_WRITE_FAILED;
159+
}
160+
*value = strncmp(buffer, "1", IQRF_GPIO_VALUE_BUFFER_SIZE - 1) == 0;
161+
close(fd);
162+
return IQRF_GPIO_ERROR_OK;
163+
#endif
164+
}
165+
166+
iqrf_gpio_error_t iqrf_gpio_set_value(int64_t pin, bool value) {
167+
#ifdef WIN32
168+
return IQRF_GPIO_ERROR_OK;
169+
#else
170+
if (pin < 0) {
171+
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
172+
return IQRF_GPIO_ERROR_INVALID_PIN;
173+
}
174+
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
175+
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_VALUE, path);
176+
int fd = open(path, O_WRONLY);
177+
if (fd == -1) {
178+
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
179+
return IQRF_GPIO_ERROR_OPEN_FAILED;
180+
}
181+
const char *buffer = value ? "1" : "0";
182+
ssize_t writtenSize = write(fd, buffer, 2);
183+
if (writtenSize == -1) {
184+
close(fd);
185+
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
186+
return IQRF_GPIO_ERROR_WRITE_FAILED;
187+
}
188+
close(fd);
189+
return IQRF_GPIO_ERROR_OK;
190+
#endif
191+
}
192+
193+
iqrf_gpio_error_t iqrf_gpio_init(int64_t pin, iqrf_gpio_direction_t direction, bool initialValue) {
194+
#ifdef WIN32
195+
return IQRF_GPIO_ERROR_OK;
196+
#else
197+
iqrf_gpio_error_t error = iqrf_gpio_export(pin);
198+
if (error) {
199+
return error;
200+
}
201+
202+
char *directionStr = direction == IQRF_GPIO_DIRECTION_IN ? "input" : "output";
203+
for (uint8_t i = 1; i <= 10; i++) {
204+
error = iqrf_gpio_set_direction(pin, direction);
205+
if (!error) {
206+
IQRF_DEBUG_PRINTF("GPIO pin #%"PRId64" direction \"%s\" is successfully set. Attempt: %d", pin, directionStr, i);
207+
break;
208+
}
209+
IQRF_DEBUG_PRINTF("Failed to set direction \"%s\" on GPIO pin #%"PRId64". Wait for 100 ms to next try: %d", directionStr, pin, i);
210+
SLEEP(100);
211+
}
212+
213+
if (direction == IQRF_GPIO_DIRECTION_OUT) {
214+
error = iqrf_gpio_set_value(pin, initialValue);
215+
if (error) {
216+
return error;
217+
}
218+
}
219+
220+
return IQRF_GPIO_ERROR_OK;
221+
#endif
222+
}
223+
224+
iqrf_gpio_error_t iqrf_gpio_init_input(int64_t pin) {
225+
return iqrf_gpio_init(pin, IQRF_GPIO_DIRECTION_IN, false);
226+
}
227+
228+
iqrf_gpio_error_t iqrf_gpio_init_output(int64_t pin, bool initialValue) {
229+
return iqrf_gpio_init(pin, IQRF_GPIO_DIRECTION_OUT, initialValue);
230+
}

0 commit comments

Comments
 (0)