gpio: add ownership gaurd
* Will not unexport if the context did not export it. Can be forced. * Checks if pin is already exported. Signed-off-by: Thomas Ingleby <thomas.c.ingleby@intel.com> Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
committed by
Brendan Le Foll
parent
5fa6f50edc
commit
7abd8f5529
16
api/gpio.h
16
api/gpio.h
@@ -159,6 +159,15 @@ maa_result_t maa_gpio_close(maa_gpio_context dev);
|
|||||||
*/
|
*/
|
||||||
maa_result_t maa_gpio_unexport(maa_gpio_context dev);
|
maa_result_t maa_gpio_unexport(maa_gpio_context dev);
|
||||||
|
|
||||||
|
/** Unexport the GPIO context (maa_gpio_close() will call this function)
|
||||||
|
* Forces regardless to to ownership.
|
||||||
|
*
|
||||||
|
* @param dev The GPIO context.
|
||||||
|
*
|
||||||
|
* @return maa result type.
|
||||||
|
*/
|
||||||
|
maa_result_t maa_gpio_unexport_force(maa_gpio_context dev);
|
||||||
|
|
||||||
/** Read the GPIO value.
|
/** Read the GPIO value.
|
||||||
*
|
*
|
||||||
* @param dev The GPIO context.
|
* @param dev The GPIO context.
|
||||||
@@ -176,6 +185,13 @@ int maa_gpio_read(maa_gpio_context dev);
|
|||||||
*/
|
*/
|
||||||
maa_result_t maa_gpio_write(maa_gpio_context dev, int value);
|
maa_result_t maa_gpio_write(maa_gpio_context dev, int value);
|
||||||
|
|
||||||
|
/** Change ownership of the context.
|
||||||
|
*
|
||||||
|
* @param dev gpio context
|
||||||
|
* @param owner does this context own the pin.
|
||||||
|
*/
|
||||||
|
maa_result_t maa_gpio_owner(maa_gpio_context dev, maa_boolean_t owner);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -56,11 +56,13 @@ typedef enum {
|
|||||||
|
|
||||||
class Gpio {
|
class Gpio {
|
||||||
public:
|
public:
|
||||||
Gpio(int pin, bool raw=false) {
|
Gpio(int pin, bool owner=true, bool raw=false) {
|
||||||
if (raw)
|
if (raw)
|
||||||
m_gpio = maa_gpio_init_raw(pin);
|
m_gpio = maa_gpio_init_raw(pin);
|
||||||
else
|
else
|
||||||
m_gpio = maa_gpio_init(pin);
|
m_gpio = maa_gpio_init(pin);
|
||||||
|
if (!owner)
|
||||||
|
maa_gpio_owner(m_gpio, 0);
|
||||||
}
|
}
|
||||||
~Gpio() {
|
~Gpio() {
|
||||||
maa_result_t x = maa_gpio_close(m_gpio);
|
maa_result_t x = maa_gpio_close(m_gpio);
|
||||||
|
|||||||
@@ -31,13 +31,14 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define SYSFS_CLASS_GPIO "/sys/class/gpio"
|
#define SYSFS_CLASS_GPIO "/sys/class/gpio"
|
||||||
#define MAX_SIZE 64
|
#define MAX_SIZE 64
|
||||||
#define POLL_TIMEOUT
|
#define POLL_TIMEOUT
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strucutre representing a gpio pin.
|
* A structure representing a gpio pin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct _gpio {
|
struct _gpio {
|
||||||
@@ -47,6 +48,7 @@ struct _gpio {
|
|||||||
void (* isr)(); /**< the interupt service request */
|
void (* isr)(); /**< the interupt service request */
|
||||||
pthread_t thread_id; /**< the isr handler thread id */
|
pthread_t thread_id; /**< the isr handler thread id */
|
||||||
int isr_value_fp; /**< the isr file pointer on the value */
|
int isr_value_fp; /**< the isr file pointer on the value */
|
||||||
|
maa_boolean_t owner; /**< If this context originally exported the pin */
|
||||||
/*@}*/
|
/*@}*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,7 +57,6 @@ maa_gpio_get_valfp(maa_gpio_context dev)
|
|||||||
{
|
{
|
||||||
char bu[MAX_SIZE];
|
char bu[MAX_SIZE];
|
||||||
sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
|
sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin);
|
||||||
|
|
||||||
dev->value_fp = open(bu, O_RDWR);
|
dev->value_fp = open(bu, O_RDWR);
|
||||||
if (dev->value_fp == -1) {
|
if (dev->value_fp == -1) {
|
||||||
return MAA_ERROR_INVALID_RESOURCE;
|
return MAA_ERROR_INVALID_RESOURCE;
|
||||||
@@ -89,17 +90,27 @@ maa_gpio_init_raw(int pin)
|
|||||||
dev->isr_value_fp = -1;
|
dev->isr_value_fp = -1;
|
||||||
dev->pin = pin;
|
dev->pin = pin;
|
||||||
|
|
||||||
int export = open(SYSFS_CLASS_GPIO "/export", O_WRONLY);
|
char directory[MAX_SIZE];
|
||||||
if (export == -1) {
|
snprintf(directory, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/", dev->pin);
|
||||||
fprintf(stderr, "Failed to open export for writing!\n");
|
struct stat dir;
|
||||||
return NULL;
|
if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) {
|
||||||
|
fprintf(stderr, "GPIO Pin already exporting, continuing.\n");
|
||||||
|
dev->owner = 0; // Not Owner
|
||||||
|
} else {
|
||||||
|
int export = open(SYSFS_CLASS_GPIO "/export", O_WRONLY);
|
||||||
|
if (export == -1) {
|
||||||
|
fprintf(stderr, "Failed to open export for writing!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
length = snprintf(bu, sizeof(bu), "%d", dev->pin);
|
||||||
|
if (write(export, bu, length*sizeof(char)) == -1) {
|
||||||
|
fprintf(stderr, "Failed to write to export\n");
|
||||||
|
close(export);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dev->owner = 1;
|
||||||
|
close(export);
|
||||||
}
|
}
|
||||||
length = snprintf(bu, sizeof(bu), "%d", dev->pin);
|
|
||||||
if (write(export, bu, length*sizeof(char)) == -1) {
|
|
||||||
fprintf(stderr, "Failed to write to export\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
close(export);
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,11 +171,11 @@ maa_gpio_interrupt_handler(void* arg)
|
|||||||
#endif
|
#endif
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
} else {
|
} else {
|
||||||
// we must have got an error code so die nicely
|
// we must have got an error code so die nicely
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
close(dev->isr_value_fp);
|
close(dev->isr_value_fp);
|
||||||
dev->isr_value_fp = -1;
|
dev->isr_value_fp = -1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,6 +412,15 @@ maa_gpio_write(maa_gpio_context dev, int value)
|
|||||||
|
|
||||||
maa_result_t
|
maa_result_t
|
||||||
maa_gpio_unexport(maa_gpio_context dev)
|
maa_gpio_unexport(maa_gpio_context dev)
|
||||||
|
{
|
||||||
|
if(dev->owner) {
|
||||||
|
return maa_gpio_unexport_force(dev);
|
||||||
|
}
|
||||||
|
return MAA_ERROR_INVALID_RESOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
maa_result_t
|
||||||
|
maa_gpio_unexport_force(maa_gpio_context dev)
|
||||||
{
|
{
|
||||||
int unexport = open(SYSFS_CLASS_GPIO "/unexport", O_WRONLY);
|
int unexport = open(SYSFS_CLASS_GPIO "/unexport", O_WRONLY);
|
||||||
if (unexport == -1) {
|
if (unexport == -1) {
|
||||||
@@ -431,3 +451,13 @@ maa_gpio_close(maa_gpio_context dev)
|
|||||||
free(dev);
|
free(dev);
|
||||||
return MAA_SUCCESS;
|
return MAA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maa_result_t
|
||||||
|
maa_gpio_owner(maa_gpio_context dev, maa_boolean_t own)
|
||||||
|
{
|
||||||
|
if (dev == NULL)
|
||||||
|
return MAA_ERROR_INVALID_RESOURCE;
|
||||||
|
dev->owner = own;
|
||||||
|
return MAA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user