Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Refactor library #34

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions include/iqrf_debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#ifdef NDEBUG
#ifndef IQRF_DEBUG_PRINT
#define IQRF_DEBUG_PRINT(fmt, ...)
#endif
#ifndef IQRF_DEBUG_PRINTF
#define IQRF_DEBUG_PRINTF(fmt, ...)
#endif
#else
#ifndef IQRF_DEBUG_PRINT
#define IQRF_DEBUG_PRINT(str) do { \
fprintf(stderr, "%s:%d - %s(): " str "\n", __FILE__, __LINE__, __func__); \
} while (0)
#endif
#ifndef IQRF_DEBUG_PRINTF
#define IQRF_DEBUG_PRINTF(fmt, ...) do { \
fprintf(stderr, "%s:%d - %s(): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__); \
} while (0)
#endif
#endif
124 changes: 124 additions & 0 deletions include/iqrf_gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#ifndef IQRF_GPIO_H
#define IQRF_GPIO_H

#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#ifndef WIN32
#include <fcntl.h>
#include <unistd.h>
#endif

#include "iqrf_debug.h"
#include "sleepWrapper.h"

#define IQRF_GPIO_SYSFS_BASE_PATH "/sys/class/gpio/"
#define IQRF_GPIO_SYSFS_BUFFER_SIZE 64
#define IQRF_GPIO_DIRECTION_BUFFER_SIZE 4
#define IQRF_GPIO_PIN_BUFFER_SIZE 20
#define IQRF_GPIO_VALUE_BUFFER_SIZE 2

static const int64_t IQRF_GPIO_PIN_UNKNOWN = -1;

typedef enum {
IQRF_GPIO_ACTION_DIRECTION,
IQRF_GPIO_ACTION_VALUE,
} iqrf_gpio_action_t;

typedef enum {
IQRF_GPIO_DIRECTION_UNKNOWN = -1,
IQRF_GPIO_DIRECTION_IN,
IQRF_GPIO_DIRECTION_OUT,
} iqrf_gpio_direction_t;

typedef enum {
IQRF_GPIO_ERROR_OK,
IQRF_GPIO_ERROR_INVALID_PIN,
IQRF_GPIO_ERROR_OPEN_FAILED,
IQRF_GPIO_ERROR_WRITE_FAILED,
IQRF_GPIO_ERROR_NULL_POINTER,
} iqrf_gpio_error_t;

/**
* Exports the GPIO pin
* @param pin GPIO pin to export
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_export(int64_t pin);

/**
* Unexports the GPIO pin
* @param pin GPIO pin to unexport
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_unexport(int64_t pin);

/**
* Retrieves the direction for GPIO pin
* @param pin GPIO pin
* @param direction GPIO pin direction
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_get_direction(int64_t pin, iqrf_gpio_direction_t *direction);

/**
* Sets the direction for GPIO pin
* @param pin GPIO pin
* @param direction GPIO pin direction
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_set_direction(int64_t pin, iqrf_gpio_direction_t direction);

/**
* Retrieves the direction for GPIO pin
* @param pin GPIO pin
* @param value GPIO pin output value
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_get_value(int64_t pin, bool *value);

/**
* Sets the direction for GPIO pin
* @param pin GPIO pin
* @param value GPIO pin output value
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_set_value(int64_t pin, bool value);

/**
* Creates sysfs path
* @param pin GPIO pin
* @param action GPIO action
* @param targetPath
*/
void iqrf_gpio_create_sysfs_path(int64_t pin, iqrf_gpio_action_t action, char *targetPath);

/**
* Initializes a GPIO pin
* @param pin GPIO pin number
* @param direction GPIO pin direction
* @param initialValue Initial output value
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_init(int64_t pin, iqrf_gpio_direction_t direction, bool initialValue);

/**
* Initializes a GPIO pin as an input
* @param pin GPIO pin number
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_init_input(int64_t pin);

/**
* Initializes a GPIO pin as an output
* @param pin GPIO pin
* @param initialValue Initial output value
* @return Execution status
*/
iqrf_gpio_error_t iqrf_gpio_init_output(int64_t pin, bool initialValue);

#endif
4 changes: 1 addition & 3 deletions spi_iqrf/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
project(spi_iqrf)

set(_SRC_FILES
spi_iqrf.c
)
set(_SRC_FILES iqrf_gpio.c spi_iqrf.c)

add_library(${PROJECT_NAME} STATIC ${_SRC_FILES})
230 changes: 230 additions & 0 deletions spi_iqrf/iqrf_gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
#include "iqrf_gpio.h"

#ifdef WIN32
#define snprintf _snprintf
#endif

static const char* IQRF_GPIO_ACTION_DIRECTION_STR = "direction";
static const char* IQRF_GPIO_ACTION_VALUE_STR = "value";
static const char* IQRF_GPIO_DIRECTION_IN_STR = "in";
static const char* IQRF_GPIO_DIRECTION_OUT_STR = "out";

void iqrf_gpio_create_sysfs_path(int64_t pin, iqrf_gpio_action_t action, char *targetPath) {
const char *actionString = action == IQRF_GPIO_ACTION_DIRECTION ? IQRF_GPIO_ACTION_DIRECTION_STR : IQRF_GPIO_ACTION_VALUE_STR;
snprintf(targetPath, IQRF_GPIO_SYSFS_BUFFER_SIZE, IQRF_GPIO_SYSFS_BASE_PATH"gpio%"PRId64"/%s", pin, actionString);
}

iqrf_gpio_error_t iqrf_gpio_export(int64_t pin) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
if (pin < 0) {
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
return IQRF_GPIO_ERROR_INVALID_PIN;
}
char *path = IQRF_GPIO_SYSFS_BASE_PATH"export";
int fd = open(path, O_WRONLY);
if (fd == -1) {
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
return IQRF_GPIO_ERROR_OPEN_FAILED;
}
char buffer[IQRF_GPIO_PIN_BUFFER_SIZE] = "";
snprintf(buffer, IQRF_GPIO_PIN_BUFFER_SIZE, "%"PRId64, pin);
ssize_t writtenSize = write(fd, buffer, IQRF_GPIO_PIN_BUFFER_SIZE);
if (writtenSize == -1) {
close(fd);
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
return IQRF_GPIO_ERROR_WRITE_FAILED;
}
close(fd);
return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_unexport(int64_t pin) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
if (pin < 0) {
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
return IQRF_GPIO_ERROR_INVALID_PIN;
}
char *path = IQRF_GPIO_SYSFS_BASE_PATH"unexport";
int fd = open(path, O_WRONLY);
if (fd == -1) {
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
return IQRF_GPIO_ERROR_OPEN_FAILED;
}
char buffer[IQRF_GPIO_PIN_BUFFER_SIZE] = "";
snprintf(buffer, IQRF_GPIO_PIN_BUFFER_SIZE, "%"PRId64, pin);
ssize_t writtenSize = write(fd, buffer, IQRF_GPIO_PIN_BUFFER_SIZE);
if (writtenSize == -1) {
close(fd);
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
return IQRF_GPIO_ERROR_WRITE_FAILED;
}
close(fd);
return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_get_direction(int64_t pin, iqrf_gpio_direction_t *direction) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
if (direction == NULL) {
return IQRF_GPIO_ERROR_NULL_POINTER;
}
if (pin < 0) {
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
return IQRF_GPIO_ERROR_INVALID_PIN;
}
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_DIRECTION, path);
int fd = open(path, O_RDONLY);
if (fd == -1) {
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
return IQRF_GPIO_ERROR_OPEN_FAILED;
}
char buffer[IQRF_GPIO_DIRECTION_BUFFER_SIZE] = "";
ssize_t readSize = read(fd, buffer, IQRF_GPIO_DIRECTION_BUFFER_SIZE);
if (readSize == -1) {
close(fd);
IQRF_DEBUG_PRINTF("Unable to read from %s", path);
return IQRF_GPIO_ERROR_WRITE_FAILED;
}
if (strncmp(buffer, IQRF_GPIO_DIRECTION_IN_STR, IQRF_GPIO_DIRECTION_BUFFER_SIZE - 1) == 0) {
*direction = IQRF_GPIO_DIRECTION_IN;
} else if (strncmp(buffer, IQRF_GPIO_DIRECTION_OUT_STR, IQRF_GPIO_DIRECTION_BUFFER_SIZE - 1) == 0) {
*direction = IQRF_GPIO_DIRECTION_OUT;
} else {
*direction = IQRF_GPIO_DIRECTION_UNKNOWN;
}
close(fd);
return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_set_direction(int64_t pin, iqrf_gpio_direction_t direction) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
if (pin < 0) {
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
return IQRF_GPIO_ERROR_INVALID_PIN;
}
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_DIRECTION, path);
int fd = open(path, O_WRONLY);
if (fd == -1) {
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
return IQRF_GPIO_ERROR_OPEN_FAILED;
}
const char *buffer = direction == IQRF_GPIO_DIRECTION_IN ? IQRF_GPIO_DIRECTION_IN_STR : IQRF_GPIO_DIRECTION_OUT_STR;
ssize_t writtenSize = write(fd, buffer, strlen(buffer));
if (writtenSize == -1) {
close(fd);
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
return IQRF_GPIO_ERROR_WRITE_FAILED;
}
close(fd);
return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_get_value(int64_t pin, bool *value) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
if (value == NULL) {
return IQRF_GPIO_ERROR_NULL_POINTER;
}
if (pin < 0) {
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
return IQRF_GPIO_ERROR_INVALID_PIN;
}
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_VALUE, path);
int fd = open(path, O_RDONLY);
if (fd == -1) {
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
return IQRF_GPIO_ERROR_OPEN_FAILED;
}
char buffer[IQRF_GPIO_VALUE_BUFFER_SIZE] = "";
ssize_t readSize = read(fd, buffer, IQRF_GPIO_VALUE_BUFFER_SIZE);
if (readSize == -1) {
close(fd);
IQRF_DEBUG_PRINTF("Unable to read from %s", path);
return IQRF_GPIO_ERROR_WRITE_FAILED;
}
*value = strncmp(buffer, "1", IQRF_GPIO_VALUE_BUFFER_SIZE - 1) == 0;
close(fd);
return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_set_value(int64_t pin, bool value) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
if (pin < 0) {
IQRF_DEBUG_PRINTF("Invalid GPIO pin number: %"PRId64, pin);
return IQRF_GPIO_ERROR_INVALID_PIN;
}
char path[IQRF_GPIO_SYSFS_BUFFER_SIZE] = "";
iqrf_gpio_create_sysfs_path(pin, IQRF_GPIO_ACTION_VALUE, path);
int fd = open(path, O_WRONLY);
if (fd == -1) {
IQRF_DEBUG_PRINTF("Unable to open path \"%s\". Reason: %s", path, strerror(errno));
return IQRF_GPIO_ERROR_OPEN_FAILED;
}
const char *buffer = value ? "1" : "0";
ssize_t writtenSize = write(fd, buffer, 2);
if (writtenSize == -1) {
close(fd);
IQRF_DEBUG_PRINTF("Unable to write '%s' into \"%s\". Reason: %s", buffer, path, strerror(errno));
return IQRF_GPIO_ERROR_WRITE_FAILED;
}
close(fd);
return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_init(int64_t pin, iqrf_gpio_direction_t direction, bool initialValue) {
#ifdef WIN32
return IQRF_GPIO_ERROR_OK;
#else
iqrf_gpio_error_t error = iqrf_gpio_export(pin);
if (error) {
return error;
}

char *directionStr = direction == IQRF_GPIO_DIRECTION_IN ? "input" : "output";
for (uint8_t i = 1; i <= 10; i++) {
error = iqrf_gpio_set_direction(pin, direction);
if (!error) {
IQRF_DEBUG_PRINTF("GPIO pin #%"PRId64" direction \"%s\" is successfully set. Attempt: %d", pin, directionStr, i);
break;
}
IQRF_DEBUG_PRINTF("Failed to set direction \"%s\" on GPIO pin #%"PRId64". Wait for 100 ms to next try: %d", directionStr, pin, i);
SLEEP(100);
}

if (direction == IQRF_GPIO_DIRECTION_OUT) {
error = iqrf_gpio_set_value(pin, initialValue);
if (error) {
return error;
}
}

return IQRF_GPIO_ERROR_OK;
#endif
}

iqrf_gpio_error_t iqrf_gpio_init_input(int64_t pin) {
return iqrf_gpio_init(pin, IQRF_GPIO_DIRECTION_IN, false);
}

iqrf_gpio_error_t iqrf_gpio_init_output(int64_t pin, bool initialValue) {
return iqrf_gpio_init(pin, IQRF_GPIO_DIRECTION_OUT, initialValue);
}
Loading