Private
Public Access
2
0

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:
Thomas Ingleby
2014-05-20 13:51:12 +01:00
committed by Brendan Le Foll
parent 5fa6f50edc
commit 7abd8f5529
3 changed files with 63 additions and 15 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}