1
0
mirror of https://github.com/xtacocorex/CHIP_IO synced 2025-07-20 04:43:21 +00:00

Fixed a bunch of error handling

This commit is contained in:
fordsfords
2016-07-04 13:56:11 -05:00
parent fd29b17796
commit 0e7d03c472
11 changed files with 787 additions and 309 deletions

View File

@ -145,7 +145,7 @@ int softpwm_set_duty_cycle(const char *key, float duty) {;
void *softpwm_thread_toggle(void *key)
{
struct softpwm *pwm;
unsigned int gpio;
int gpio;
struct timespec tim_on;
struct timespec tim_off;
unsigned int sec;
@ -237,7 +237,7 @@ int softpwm_start(const char *key, float duty, float freq, int polarity)
struct softpwm *new_pwm, *pwm;
pthread_t new_thread;
pthread_mutex_t *new_params_lock;
unsigned int gpio;
int gpio;
int ret;
get_gpio_number(key, &gpio);
@ -296,7 +296,7 @@ int softpwm_start(const char *key, float duty, float freq, int polarity)
int softpwm_disable(const char *key)
{
struct softpwm *pwm, *temp, *prev_pwm = NULL;
unsigned int gpio = 0;
int gpio = 0;
// remove from list
pwm = exported_pwms;

View File

@ -42,6 +42,7 @@ SOFTWARE.
#include "common.h"
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
@ -49,24 +50,25 @@ SOFTWARE.
int setup_error = 0;
int module_setup = 0;
// I have no idea if this table is correct, we shall see - Robert Wolterman
pins_t pins_info[] = {
{ "GND", "U13_1", 0, BASE_METHOD_AS_IS, -1, -1},
{ "CHG-IN", "U13_2", 0, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-5V", "U13_3", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_4", 0, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-3V3", "U13_5", 0, BASE_METHOD_AS_IS, -1, -1},
{ "TS", "U13_6", 0, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-1V8", "U13_7", 0, BASE_METHOD_AS_IS, -1, -1},
{ "BAT", "U13_8", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_1", -1, BASE_METHOD_AS_IS, -1, -1},
{ "CHG-IN", "U13_2", -1, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-5V", "U13_3", -1, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_4", -1, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-3V3", "U13_5", -1, BASE_METHOD_AS_IS, -1, -1},
{ "TS", "U13_6", -1, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-1V8", "U13_7", -1, BASE_METHOD_AS_IS, -1, -1},
{ "BAT", "U13_8", -1, BASE_METHOD_AS_IS, -1, -1},
{ "TWI1-SDA", "U13_9", 48, BASE_METHOD_AS_IS, -1, -1},
{ "PWRON", "U13_10", 0, BASE_METHOD_AS_IS, -1, -1},
{ "PWRON", "U13_10", -1, BASE_METHOD_AS_IS, -1, -1},
{ "TWI1-SCK", "U13_11", 47, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_12", 0, BASE_METHOD_AS_IS, -1, -1},
{ "X1", "U13_13", 0, BASE_METHOD_AS_IS, -1, -1},
{ "X2", "U13_14", 0, BASE_METHOD_AS_IS, -1, -1},
{ "Y1", "U13_15", 0, BASE_METHOD_AS_IS, -1, -1},
{ "Y2", "U13_16", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_12", -1, BASE_METHOD_AS_IS, -1, -1},
{ "X1", "U13_13", -1, BASE_METHOD_AS_IS, -1, -1},
{ "X2", "U13_14", -1, BASE_METHOD_AS_IS, -1, -1},
{ "Y1", "U13_15", -1, BASE_METHOD_AS_IS, -1, -1},
{ "Y2", "U13_16", -1, BASE_METHOD_AS_IS, -1, -1},
{ "LCD-D2", "U13_17", 98, BASE_METHOD_AS_IS, -1, -1},
{ "PWM0", "U13_18", 34, BASE_METHOD_AS_IS, 0, -1},
{ "LCD-D4", "U13_19", 100, BASE_METHOD_AS_IS, -1, -1},
@ -89,20 +91,20 @@ pins_t pins_info[] = {
{ "LCD-D23", "U13_36", 119, BASE_METHOD_AS_IS, -1, -1},
{ "LCD-VSYNC", "U13_37", 123, BASE_METHOD_AS_IS, -1, -1},
{ "LCD-HSYNC", "U13_38", 122, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_39", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U13_39", -1, BASE_METHOD_AS_IS, -1, -1},
{ "LCD-DE", "U13_40", 121, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_1", 0, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-5V", "U14_2", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_1", -1, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-5V", "U14_2", -1, BASE_METHOD_AS_IS, -1, -1},
{ "UART1-TX", "U14_3", 195, BASE_METHOD_AS_IS, -1, -1},
{ "HPL", "U14_4", 0, BASE_METHOD_AS_IS, -1, -1},
{ "HPL", "U14_4", -1, BASE_METHOD_AS_IS, -1, -1},
{ "UART1-RX", "U14_5", 196, BASE_METHOD_AS_IS, -1, -1},
{ "HPCOM", "U14_6", 0, BASE_METHOD_AS_IS, -1, -1},
{ "FEL", "U14_7", 0, BASE_METHOD_AS_IS, -1, -1},
{ "HPR", "U14_8", 0, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-3V3", "U14_9", 0, BASE_METHOD_AS_IS, -1, -1},
{ "MICM", "U14_10", 0, BASE_METHOD_AS_IS, -1, -1},
{ "LRADC", "U14_11", 0, BASE_METHOD_AS_IS, -1, 0},
{ "MICIN1", "U14_12", 0, BASE_METHOD_AS_IS, -1, -1},
{ "HPCOM", "U14_6", -1, BASE_METHOD_AS_IS, -1, -1},
{ "FEL", "U14_7", -1, BASE_METHOD_AS_IS, -1, -1},
{ "HPR", "U14_8", -1, BASE_METHOD_AS_IS, -1, -1},
{ "VCC-3V3", "U14_9", -1, BASE_METHOD_AS_IS, -1, -1},
{ "MICM", "U14_10", -1, BASE_METHOD_AS_IS, -1, -1},
{ "LRADC", "U14_11", -1, BASE_METHOD_AS_IS, -1, 0},
{ "MICIN1", "U14_12", -1, BASE_METHOD_AS_IS, -1, -1},
{ "XIO-P0", "U14_13", 0, BASE_METHOD_XIO, -1, -1},
{ "XIO-P1", "U14_14", 1, BASE_METHOD_XIO, -1, -1},
{ "XIO-P2", "U14_15", 2, BASE_METHOD_XIO, -1, -1},
@ -111,8 +113,8 @@ pins_t pins_info[] = {
{ "XIO-P5", "U14_18", 5, BASE_METHOD_XIO, -1, -1},
{ "XIO-P6", "U14_19", 6, BASE_METHOD_XIO, -1, -1},
{ "XIO-P7", "U14_20", 7, BASE_METHOD_XIO, -1, -1},
{ "GND", "U14_21", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_22", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_21", -1, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_22", -1, BASE_METHOD_AS_IS, -1, -1},
{ "AP-EINT1", "U14_23", 193, BASE_METHOD_AS_IS, -1, -1},
{ "AP-EINT3", "U14_24", 35, BASE_METHOD_AS_IS, -1, -1},
{ "TWI2-SDA", "U14_25", 50, BASE_METHOD_AS_IS, -1, -1},
@ -129,9 +131,9 @@ pins_t pins_info[] = {
{ "CSID5", "U14_36", 137, BASE_METHOD_AS_IS, -1, -1},
{ "CSID6", "U14_37", 138, BASE_METHOD_AS_IS, -1, -1},
{ "CSID7", "U14_38", 139, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_39", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_40", 0, BASE_METHOD_AS_IS, -1, -1},
{ NULL, NULL, 0, 0, -1, -1}
{ "GND", "U14_39", -1, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_40", -1, BASE_METHOD_AS_IS, -1, -1},
{ NULL, NULL, -1, 0, -1, -1}
};
@ -144,14 +146,14 @@ pins_t pins_info[] = {
// http://stackoverflow.com/questions/612097/how-can-i-get-the-list-of-files-in-a-directory-using-c-or-c
#define GPIO_PATH "/sys/class/gpio"
#define EXPANDER "pcf8574a\n"
int num_get_xio_base = 0; /* for self-test purposes */
/* returns -1 for error */
int get_xio_base(void)
{
char label_file[FILENAME_BUFFER_SIZE];
FILE *label_fp;
char base_file[FILENAME_BUFFER_SIZE];
FILE *base_fp;
char input_line[80];
// Makes use of static variable xio_base_address to maintain state between
// calls. First time this is called, xio_base_address is -1, so the actual
// base address is calculated and stored in xio_base_address. Subsequent
@ -162,33 +164,55 @@ int get_xio_base(void)
struct dirent *ent;
struct stat sbuf;
if (xio_base_address == -1 && (dir = opendir (GPIO_PATH)) != NULL) {
if (xio_base_address != -1)
return xio_base_address;
dir = opendir (GPIO_PATH);
if (dir == NULL) {
char err[256];
snprintf(err, sizeof(err), "get_xio_base: could not open '%s' (%s)", GPIO_PATH, strerror(errno));
add_error_msg(err);
return -1;
}
while (xio_base_address == -1 && (ent = readdir (dir)) != NULL) {
lstat(ent->d_name,&sbuf);
if (S_ISDIR(sbuf.st_mode)) {
if (strcmp(".",ent->d_name) == 0 || strcmp("..",ent->d_name) == 0) {
continue; /* skip "." and ".." entries */
}
snprintf(label_file, sizeof(label_file), "%s/%s/label", GPIO_PATH, ent->d_name); BUF2SMALL(label_file);
label_fp = fopen(label_file, "r");
if (label_fp != NULL) {
char *s = fgets(input_line, sizeof(input_line), label_fp); BUF2SMALL(input_line); ASSRT(s);
char input_line[80]; input_line[0] = '\0';
char *s = fgets(input_line, sizeof(input_line), label_fp); BUF2SMALL(input_line);
fclose(label_fp);
if (strcmp(input_line, EXPANDER) == 0) {
if (s != NULL && strcmp(input_line, EXPANDER) == 0) {
/* Found the expander, get the contents of base */
snprintf(base_file, sizeof(base_file), "%s/%s/base", GPIO_PATH, ent->d_name); BUF2SMALL(base_file);
base_fp = fopen(base_file, "r"); ASSRT(base_fp != NULL);
s = fgets(input_line, sizeof(input_line), base_fp); BUF2SMALL(input_line); ASSRT(s);
base_fp = fopen(base_file, "r");
if (base_fp == NULL) {
char err[80];
snprintf(err, sizeof(err), "get_xio_base: could not open '%s' (%s)", base_file, strerror(errno));
add_error_msg(err);
break; /* error, exit loop */
}
s = fgets(input_line, sizeof(input_line), base_fp); BUF2SMALL(input_line);
fclose(base_fp);
if (s == NULL) {
char err[80];
snprintf(err, sizeof(err), "get_xio_base: could not read '%s' (%s)", base_file, strerror(errno));
add_error_msg(err);
break; /* error, exit loop */
}
/* Remember the value in the static local. */
xio_base_address = atoi(input_line); ASSRT(xio_base_address > 0);
num_get_xio_base++; /* for self-test purposes */
xio_base_address = atoi(input_line);
}
} /* if label file is open */
} /* if isdir */
} /* while */
closedir (dir);
}
return xio_base_address;
} /* get_xio_base */
@ -197,6 +221,7 @@ int get_xio_base(void)
int gpio_number(pins_t *pin)
{
int gpio_num = -1;
int xio_base;
switch (pin->base_method) {
case BASE_METHOD_AS_IS:
@ -204,11 +229,16 @@ int gpio_number(pins_t *pin)
break;
case BASE_METHOD_XIO:
gpio_num = pin->gpio + get_xio_base();
xio_base = get_xio_base();
if (xio_base <= 0) {
char err[80]; snprintf(err, sizeof(err), "gpio_number: %d found for %s", xio_base, pin->name);
add_error_msg(err);
break; /* error, exit switch */
}
gpio_num = pin->gpio + xio_base;
break;
}
ASSRT(gpio_num != -1);
return gpio_num;
} /* gpio_number */
@ -221,7 +251,7 @@ int lookup_gpio_by_key(const char *key)
return gpio_number(p);
}
}
return 0;
return -1;
}
int lookup_gpio_by_name(const char *name)
@ -232,7 +262,7 @@ int lookup_gpio_by_name(const char *name)
return gpio_number(p);
}
}
return 0;
return -1;
}
int lookup_ain_by_key(const char *key)
@ -325,15 +355,18 @@ int get_pwm_key_by_name(const char *name, char *key)
return 0;
}
int get_gpio_number(const char *key, unsigned int *gpio)
int get_gpio_number(const char *key, int *gpio)
{
int status = 0; /* assume success */
*gpio = lookup_gpio_by_key(key);
if (!*gpio) {
if (*gpio <= 0) {
*gpio = lookup_gpio_by_name(key);
if (*gpio <= 0) {
status = -1; /* error */
}
return 0;
}
return status;
}
int get_key(const char *input, char *key)
@ -421,73 +454,136 @@ int get_spi_bus_path_number(unsigned int spi)
}
struct dyn_int_array {
int num_elements;
int *array;
};
// We do not know at compile time how many GPIOs there are, so it is not safe
// to declare per-GPIO arrays with a static size. The "dyn_int_array_*"
// functions implement a dynamic integer array which grows as needed at run
// time. Users of a dynamic array do not access the array directly, but by
// access methods.
//
// To use, declare a dyn_int_array_t pointer initialized to NULL:
// dyn_int_array_t *my_per_gpio_array = NULL;
// If declared as a local to a function, consider making it "static":
// static dyn_int_array_t *my_per_gpio_array = NULL;
// The access methods must be passed a pointer to this pointer.
// Then when reading and writing to array elements, it is usually important
// to supply a "default value". This is so that as the array grows, the
// as-yet unused elements can be initialzied to a desired value.
// my_index = 100;
// dyn_int_array_set(&my_per_gpio_array, my_index, my_value, -1);
// This initializes elements 0-99 to -1, and element 100 to my_value. For
// efficiency purposes, it grows the array to half again larger than it needs
// to. Thus, elements 101-149 will be initialized to -1.
//
// If an element past the end of the array is read, the array is once again
// grown, with initialization:
// my_index = 500;
// int val = dyn_int_array_get(&my_per_gpio_array, my_index, -1);
// This grows the array to 749 (half again larger than 500) and initializes all
// the new elements to -1, including element 500, which is then returned.
void *dyn_int_array_create(int initial_num_elements, int initial_val)
/* internal function; only called by access methods. */
dyn_int_array_t *dyn_int_array_create(int initial_num_elements, int initial_val)
{
struct dyn_int_array *new_array = (struct dyn_int_array *)malloc(sizeof(struct dyn_int_array));
ASSRT(new_array != NULL);
dyn_int_array_t *new_array = (dyn_int_array_t *)malloc(sizeof(dyn_int_array_t));
ASSRT(new_array != NULL); /* out of memory */
new_array->num_elements = initial_num_elements;
new_array->array = (int *)malloc(initial_num_elements * sizeof(int));
ASSRT(new_array->array != NULL);
new_array->content = (int *)malloc(initial_num_elements * sizeof(int));
ASSRT(new_array->content != NULL); /* out of memory */
int i;
for (i = 0; i < initial_num_elements; i++)
new_array->array[i] = initial_val;
new_array->content[i] = initial_val;
return (void *)new_array;
return new_array;
} /* dyn_int_array_create */
void dyn_int_array_set(void **in_array, int i, int val, int initial_val)
void dyn_int_array_set(dyn_int_array_t **in_array, int i, int val, int initial_val)
{
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
if (array == NULL)
array = dyn_int_array_create(i * 3 / 2, initial_val);
dyn_int_array_t *array = *in_array;
if (array == NULL) { /* if array hasn't been created yet */
array = dyn_int_array_create((i+1) * 3 / 2, initial_val);
*in_array = array;
}
if (i >= array->num_elements) {
int new_num_elements = i * 3 / 2; /* half-again larger than current request */
array->array = realloc(array->array, new_num_elements * sizeof(int));
ASSRT(array->array != NULL);
int new_num_elements = (i+1) * 3 / 2; /* half-again larger than current request */
array->content = realloc(array->content, new_num_elements * sizeof(int));
ASSRT(array->content != NULL); /* out of memory */
// Zero out the newly allocated elements.
while (array->num_elements < new_num_elements) {
array->array[array->num_elements] = initial_val;
array->content[array->num_elements] = initial_val;
array->num_elements ++;
}
}
array->array[i] = val;
*in_array = (void *)array;
array->content[i] = val;
} /* dyn_int_array_set */
int dyn_int_array_get(void **in_array, int i, int initial_val)
int dyn_int_array_get(dyn_int_array_t **in_array, int i, int initial_val)
{
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
if (array == NULL)
array = dyn_int_array_create(i * 3 / 2, initial_val);
dyn_int_array_t *array = *in_array;
if (array == NULL) { /* if array hasn't been created yet */
array = dyn_int_array_create((i+1) * 3 / 2, initial_val);
*in_array = array;
}
if (i >= array->num_elements) {
int new_num_elements = i * 3 / 2; /* half-again larger than current request */
array->array = realloc(array->array, new_num_elements * sizeof(int));
ASSRT(array->array != NULL);
int new_num_elements = (i+1) * 3 / 2; /* half-again larger than current request */
array->content = realloc(array->content, new_num_elements * sizeof(int));
ASSRT(array->content != NULL); /* out of memory */
// Zero out the newly allocated elements.
while (array->num_elements < new_num_elements) {
array->array[array->num_elements] = initial_val;
array->content[array->num_elements] = initial_val;
array->num_elements ++;
}
}
return array->array[i];
*in_array = (void *)array;
return array->content[i];
} /* dyn_int_array_get */
void dyn_int_array_delete(void **in_array)
void dyn_int_array_delete(dyn_int_array_t **in_array)
{
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
free(array->array);
dyn_int_array_t *array = *in_array;
free(array->content);
free(array);
} /* dyn_int_array_delete */
char error_msg_buff[1024]; /* written to when an error must be returned */
void clear_error_msg(void)
{
error_msg_buff[0] = '\0';
}
char *get_error_msg(void)
{
return error_msg_buff;
}
void add_error_msg(char *msg)
{
int buff_len = strnlen(error_msg_buff, sizeof(error_msg_buff)); ASSRT(buff_len < sizeof(error_msg_buff));
int remaining = sizeof(error_msg_buff) - buff_len - 1; /* leave room for final null */
if (buff_len > 0 && remaining > 0) { /* include newline between messages */
error_msg_buff[buff_len] = '\n';
buff_len ++;
remaining --;
}
char *start = &error_msg_buff[buff_len]; /* points at null in the buffer */
int msg_len = strlen(msg);
if (msg_len >= remaining)
msg_len = remaining; /* don't overflow buffer; truncate message */
if (msg_len > 0)
memcpy(start, msg, msg_len);
start[msg_len] = '\0';
}

View File

@ -69,6 +69,14 @@ typedef struct pins_t {
int ain;
} pins_t;
struct dyn_int_array_s {
int num_elements;
int *content;
};
typedef struct dyn_int_array_s dyn_int_array_t;
#define FILENAME_BUFFER_SIZE 128
int setup_error;
@ -84,12 +92,15 @@ int copy_key_by_key(const char *input_key, char *key);
int copy_pwm_key_by_key(const char *input_key, char *key);
int get_key_by_name(const char *name, char *key);
int get_pwm_key_by_name(const char *name, char *key);
int get_gpio_number(const char *key, unsigned int *gpio);
int get_gpio_number(const char *key, int *gpio);
int get_key(const char *input, char *key);
int get_pwm_key(const char *input, char *key);
int get_adc_ain(const char *key, unsigned int *ain);
int build_path(const char *partial_path, const char *prefix, char *full_path, size_t full_path_len);
int get_spi_bus_path_number(unsigned int spi);
void dyn_int_array_set(void **in_array, int i, int val, int initial_val);
int dyn_int_array_get(void **in_array, int i, int initial_val);
void dyn_int_array_delete(void **in_array);
void dyn_int_array_set(dyn_int_array_t **in_array, int i, int val, int initial_val);
int dyn_int_array_get(dyn_int_array_t **in_array, int i, int initial_val);
void dyn_int_array_delete(dyn_int_array_t **in_array);
void clear_error_msg(void);
char *get_error_msg(void);
void add_error_msg(char *msg);

View File

@ -42,6 +42,7 @@ SOFTWARE.
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "event_gpio.h"
#include "common.h"
@ -52,7 +53,7 @@ const char *stredge[4] = {"none", "rising", "falling", "both"};
struct fdx
{
int fd;
unsigned int gpio;
int gpio;
int initial;
unsigned int is_evented;
struct fdx *next;
@ -62,8 +63,8 @@ struct fdx *fd_list = NULL;
// event callbacks
struct callback
{
unsigned int gpio;
void (*func)(unsigned int gpio);
int gpio;
void (*func)(int gpio);
struct callback *next;
};
struct callback *callbacks = NULL;
@ -71,38 +72,47 @@ struct callback *callbacks = NULL;
// gpio exports
struct gpio_exp
{
unsigned int gpio;
int gpio;
struct gpio_exp *next;
};
struct gpio_exp *exported_gpios = NULL;
pthread_t threads;
void *event_occurred = NULL;
dyn_int_array_t *event_occurred = NULL;
int thread_running = 0;
int epfd = -1;
int gpio_export(unsigned int gpio)
int gpio_export(int gpio)
{
int fd, len;
char str_gpio[16];
int fd, len, e_no;
char filename[MAX_FILENAME];
char str_gpio[80];
struct gpio_exp *new_gpio, *g;
if ((fd = open("/sys/class/gpio/export", O_WRONLY)) < 0)
snprintf(filename, sizeof(filename), "/sys/class/gpio/export"); BUF2SMALL(filename);
if ((fd = open(filename, O_WRONLY)) < 0)
{
char err[80];
snprintf(err, sizeof(err), "gpio_export: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len);
ssize_t s = write(fd, str_gpio, len); e_no = errno;
close(fd);
if (s != len)
{
char err[80];
snprintf(err, sizeof(err), "gpio_export: could not write '%s' to %s (%s)", str_gpio, filename, strerror(e_no));
add_error_msg(err);
return -1;
}
// add to list
new_gpio = malloc(sizeof(struct gpio_exp));
if (new_gpio == 0)
return -1; // out of memory
new_gpio = malloc(sizeof(struct gpio_exp)); ASSRT(new_gpio != NULL);
new_gpio->gpio = gpio;
new_gpio->next = NULL;
@ -118,10 +128,12 @@ int gpio_export(unsigned int gpio)
g = g->next;
g->next = new_gpio;
}
return 0;
}
void close_value_fd(unsigned int gpio)
return 0;
} /* gpio_export */
void close_value_fd(int gpio)
{
struct fdx *f = fd_list;
struct fdx *temp;
@ -144,9 +156,10 @@ void close_value_fd(unsigned int gpio)
f = f->next;
}
}
}
} /* close_value_fd */
int fd_lookup(unsigned int gpio)
int fd_lookup(int gpio)
{
struct fdx *f = fd_list;
while (f != NULL)
@ -155,16 +168,16 @@ int fd_lookup(unsigned int gpio)
return f->fd;
f = f->next;
}
return 0;
}
int add_fd_list(unsigned int gpio, int fd)
int add_fd_list(int gpio, int fd)
{
struct fdx *new_fd;
new_fd = malloc(sizeof(struct fdx));
if (new_fd == 0)
return -1; // out of memory
new_fd = malloc(sizeof(struct fdx)); ASSRT(new_fd != NULL);
new_fd->fd = fd;
new_fd->gpio = gpio;
@ -176,10 +189,11 @@ int add_fd_list(unsigned int gpio, int fd)
new_fd->next = fd_list;
}
fd_list = new_fd;
return 0;
}
int open_value_file(unsigned int gpio)
int open_value_file(int gpio)
{
int fd;
char filename[MAX_FILENAME];
@ -188,26 +202,44 @@ int open_value_file(unsigned int gpio)
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio); BUF2SMALL(filename);
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) {
char err[80];
snprintf(err, sizeof(err), "open_value_file: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
add_fd_list(gpio, fd);
return fd;
}
int gpio_unexport(unsigned int gpio)
return fd;
} /* open_value_file */
int gpio_unexport(int gpio)
{
int fd, len;
int fd, len, e_no;
char filename[MAX_FILENAME];
char str_gpio[16];
struct gpio_exp *g, *temp, *prev_g = NULL;
close_value_fd(gpio);
if ((fd = open("/sys/class/gpio/unexport", O_WRONLY)) < 0)
snprintf(filename, sizeof(filename), "/sys/class/gpio/unexport"); BUF2SMALL(filename);
if ((fd = open(filename, O_WRONLY)) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_unexport: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len); ASSRT(s == len);
ssize_t s = write(fd, str_gpio, len); e_no = errno;
close(fd);
if (s != len) {
char err[80];
snprintf(err, sizeof(err), "gpio_unexport: could not write '%s' (%s)", filename, strerror(e_no));
add_error_msg(err);
return -1;
}
// remove from list
g = exported_gpios;
@ -227,61 +259,100 @@ int gpio_unexport(unsigned int gpio)
g = g->next;
}
}
return 0;
}
int gpio_set_direction(unsigned int gpio, unsigned int in_flag)
int gpio_set_direction(int gpio, unsigned int in_flag)
{
int fd;
char filename[MAX_FILENAME];
char direction[16] = { 0 };
int fd, e_no;
char filename[MAX_FILENAME]; filename[0] = '\0';
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", gpio); BUF2SMALL(filename);
if ((fd = open(filename, O_WRONLY)) < 0)
if ((fd = open(filename, O_WRONLY)) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_direction: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
char direction[16];
if (in_flag) {
strncpy(direction, "out", ARRAY_SIZE(direction) - 1);
} else {
strncpy(direction, "in", ARRAY_SIZE(direction) - 1);
}
ssize_t s = write(fd, direction, strlen(direction)); ASSRT(s == strlen(direction));
ssize_t s = write(fd, direction, strlen(direction)); e_no = errno;
close(fd);
if (s != strlen(direction)) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_direction: could not write '%s' (%s)", filename, strerror(e_no));
add_error_msg(err);
return -1;
}
return 0;
}
int gpio_get_direction(unsigned int gpio, unsigned int *value)
int gpio_get_direction(int gpio, unsigned int *value)
{
int fd;
char direction[4] = { 0 };
int fd, e_no;
char filename[MAX_FILENAME];
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", gpio); BUF2SMALL(filename);
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_get_direction: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
lseek(fd, 0, SEEK_SET);
ssize_t s = read(fd, &direction, sizeof(direction) - 1); ASSRT(s > 0);
if (lseek(fd, 0, SEEK_SET) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_get_direction: could not seek GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return -1;
}
if (strcmp(direction, "out") == 0) {
char direction[4] = { 0 }; /* make sure read is null-terminated */
ssize_t s = read(fd, &direction, sizeof(direction) - 1); e_no = errno;
close(fd);
if (s < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_direction: could not read '%s' (%s)", filename, strerror(e_no));
add_error_msg(err);
return -1;
}
if (strcmp(direction, "out") == 0)
*value = OUTPUT;
} else {
else if (strcmp(direction, "in") == 0)
*value = INPUT;
else {
char err[80];
snprintf(err, sizeof(err), "gpio_set_direction: unexpected '%s' found in %s", direction, filename);
add_error_msg(err);
return -1;
}
return 0;
}
} /* gpio_set_direction */
int gpio_set_value(unsigned int gpio, unsigned int value)
int gpio_set_value(int gpio, unsigned int value)
{
int fd;
int fd, e_no;
char filename[MAX_FILENAME];
char vstr[16];
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio); BUF2SMALL(filename);
if ((fd = open(filename, O_WRONLY)) < 0)
if ((fd = open(filename, O_WRONLY)) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_value: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
if (value) {
strncpy(vstr, "1", ARRAY_SIZE(vstr) - 1);
@ -289,53 +360,89 @@ int gpio_set_value(unsigned int gpio, unsigned int value)
strncpy(vstr, "0", ARRAY_SIZE(vstr) - 1);
}
ssize_t s = write(fd, vstr, strlen(vstr));
ssize_t s = write(fd, vstr, strlen(vstr)); e_no = errno;
close(fd);
if (s != strlen(vstr))
if (s != strlen(vstr)) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_value: could not write '%s' to %s (%s)", vstr, filename, strerror(e_no));
add_error_msg(err);
return -2;
}
return 0;
}
int gpio_get_value(unsigned int gpio, unsigned int *value)
int gpio_get_value(int gpio, unsigned int *value)
{
int fd = fd_lookup(gpio);
char ch;
if (!fd)
{
if ((fd = open_value_file(gpio)) == -1)
if ((fd = open_value_file(gpio)) == -1) {
char err[80];
snprintf(err, sizeof(err), "gpio_get_value: could not open GPIO %d value file", gpio);
add_error_msg(err);
return -1;
}
}
if (lseek(fd, 0, SEEK_SET) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_get_value: could not seek GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return -1;
}
ssize_t s = read(fd, &ch, sizeof(ch));
if (s < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_get_value: could not read GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return -1;
}
lseek(fd, 0, SEEK_SET);
ssize_t s = read(fd, &ch, sizeof(ch)); ASSRT(s > 0);
if (ch != '0') {
if (ch == '1') {
*value = 1;
} else {
} else if (ch == '0') {
*value = 0;
} else {
char err[80];
snprintf(err, sizeof(err), "gpio_get_value: unrecognized read GPIO %d (%c)", gpio, ch);
add_error_msg(err);
return -1;
}
return 0;
}
int gpio_set_edge(unsigned int gpio, unsigned int edge)
int gpio_set_edge(int gpio, unsigned int edge)
{
int fd;
char filename[MAX_FILENAME];
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio); BUF2SMALL(filename);
if ((fd = open(filename, O_WRONLY)) < 0)
if ((fd = open(filename, O_WRONLY)) < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_edge: could not open '%s' (%s)", filename, strerror(errno));
add_error_msg(err);
return -1;
}
ssize_t s = write(fd, stredge[edge], strlen(stredge[edge]) + 1); ASSRT(s == strlen(stredge[edge]) + 1);
ssize_t s = write(fd, stredge[edge], strlen(stredge[edge]) + 1);
if (s < 0) {
char err[80];
snprintf(err, sizeof(err), "gpio_set_edge: could not write '%s' to %s (%s)", stredge[edge], filename, strerror(errno));
add_error_msg(err);
return -1;
}
close(fd);
return 0;
}
unsigned int gpio_lookup(int fd)
int gpio_lookup(int fd)
{
struct fdx *f = fd_list;
while (f != NULL)
@ -344,7 +451,8 @@ unsigned int gpio_lookup(int fd)
return f->gpio;
f = f->next;
}
return 0;
return -1;
}
void exports_cleanup(void)
@ -354,14 +462,12 @@ void exports_cleanup(void)
gpio_unexport(exported_gpios->gpio);
}
int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio))
int add_edge_callback(int gpio, void (*func)(int gpio))
{
struct callback *cb = callbacks;
struct callback *new_cb;
new_cb = malloc(sizeof(struct callback));
if (new_cb == 0)
return -1; // out of memory
new_cb = malloc(sizeof(struct callback)); ASSRT(new_cb != NULL);
new_cb->gpio = gpio;
new_cb->func = func;
@ -379,7 +485,7 @@ int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio))
return 0;
}
void run_callbacks(unsigned int gpio)
void run_callbacks(int gpio)
{
struct callback *cb = callbacks;
while (cb != NULL)
@ -390,7 +496,7 @@ void run_callbacks(unsigned int gpio)
}
}
void remove_callbacks(unsigned int gpio)
void remove_callbacks(int gpio)
{
struct callback *cb = callbacks;
struct callback *temp;
@ -414,7 +520,7 @@ void remove_callbacks(unsigned int gpio)
}
}
void set_initial_false(unsigned int gpio)
void set_initial_false(int gpio)
{
struct fdx *f = fd_list;
@ -426,7 +532,7 @@ void set_initial_false(unsigned int gpio)
}
}
int gpio_initial(unsigned int gpio)
int gpio_initial(int gpio)
{
struct fdx *f = fd_list;
@ -443,7 +549,7 @@ void *poll_thread(void *threadarg)
{
struct epoll_event events;
char buf;
unsigned int gpio;
int gpio;
int n;
thread_running = 1;
@ -475,7 +581,7 @@ void *poll_thread(void *threadarg)
pthread_exit(NULL);
}
int gpio_is_evented(unsigned int gpio)
int gpio_is_evented(int gpio)
{
struct fdx *f = fd_list;
while (f != NULL)
@ -487,7 +593,7 @@ int gpio_is_evented(unsigned int gpio)
return 0;
}
int gpio_event_add(unsigned int gpio)
int gpio_event_add(int gpio)
{
struct fdx *f = fd_list;
while (f != NULL)
@ -505,7 +611,7 @@ int gpio_event_add(unsigned int gpio)
return 0;
}
int gpio_event_remove(unsigned int gpio)
int gpio_event_remove(int gpio)
{
struct fdx *f = fd_list;
while (f != NULL)
@ -521,7 +627,7 @@ int gpio_event_remove(unsigned int gpio)
}
// add_edge_detect assumes the caller has ensured the GPIO is already exported.
int add_edge_detect(unsigned int gpio, unsigned int edge)
int add_edge_detect(int gpio, unsigned int edge)
// return values:
// 0 - Success
// 1 - Edge detection already added
@ -537,18 +643,34 @@ int add_edge_detect(unsigned int gpio, unsigned int edge)
return 1;
// export /sys/class/gpio interface
gpio_set_direction(gpio, 0); // 0=input
gpio_set_edge(gpio, edge);
if (gpio_set_direction(gpio, 0) < 0) {
char err[80];
snprintf(err, sizeof(err), "add_edge_detect: could not set direction for GPIO %d", gpio);
add_error_msg(err);
return 2;
}
if (gpio_set_edge(gpio, edge) < 0) {
char err[80];
snprintf(err, sizeof(err), "add_edge_detect: could not set edge for GPIO %d", gpio);
add_error_msg(err);
return 2;
}
if (!fd)
{
if ((fd = open_value_file(gpio)) == -1) {
char err[80];
snprintf(err, sizeof(err), "add_edge_detect: could not open GPIO %d value file", gpio);
add_error_msg(err);
return 2;
}
}
// create epfd if not already open
if ((epfd == -1) && ((epfd = epoll_create(1)) == -1)) {
char err[80];
snprintf(err, sizeof(err), "add_edge_detect: could not epoll_create GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return 2;
}
@ -556,6 +678,9 @@ int add_edge_detect(unsigned int gpio, unsigned int edge)
ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
ev.data.fd = fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
char err[80];
snprintf(err, sizeof(err), "add_edge_detect: could not epoll_ctl GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return 2;
}
@ -563,14 +688,18 @@ int add_edge_detect(unsigned int gpio, unsigned int edge)
if (!thread_running)
{
if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
char err[80];
snprintf(err, sizeof(err), "add_edge_detect: could not pthread_create GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return 2;
}
}
return 0;
}
} /* add_edge_detect */
void remove_edge_detect(unsigned int gpio)
void remove_edge_detect(int gpio)
{
struct epoll_event ev;
int fd = fd_lookup(gpio);
@ -591,7 +720,8 @@ void remove_edge_detect(unsigned int gpio)
dyn_int_array_set(&event_occurred, gpio, 0, 0);
}
int event_detected(unsigned int gpio)
int event_detected(int gpio)
{
if (dyn_int_array_get(&event_occurred, gpio, 0)) {
dyn_int_array_set(&event_occurred, gpio, 0, 0);
@ -608,7 +738,8 @@ void event_cleanup(void)
exports_cleanup();
}
int blocking_wait_for_edge(unsigned int gpio, unsigned int edge)
// blocking_wait_for_edge assumes the caller has ensured the GPIO is already exported.
int blocking_wait_for_edge(int gpio, unsigned int edge)
// standalone from all the event functions above
{
int fd = fd_lookup(gpio);
@ -616,51 +747,79 @@ int blocking_wait_for_edge(unsigned int gpio, unsigned int edge)
struct epoll_event events, ev;
char buf;
if ((epfd = epoll_create(1)) == -1)
if ((epfd = epoll_create(1)) == -1) {
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: could not epoll_create GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return 1;
}
// check to see if this gpio has been added already, if not, mark as added
if (gpio_event_add(gpio) != 0)
if (gpio_event_add(gpio) != 0) {
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: could not add event for GPIO %d", gpio);
add_error_msg(err);
return 2;
}
// export /sys/class/gpio interface
gpio_export(gpio); // ignore errors
gpio_set_direction(gpio, 0); // 0=input
gpio_set_edge(gpio, edge);
if (!fd)
{
if ((fd = open_value_file(gpio)) == -1)
if ((fd = open_value_file(gpio)) == -1) {
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: could not open GPIO %d value file", gpio);
add_error_msg(err);
return 3;
}
}
// add to epoll fd
ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
ev.data.fd = fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
{
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: could not epoll_ctl GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
gpio_event_remove(gpio);
return 4;
}
// epoll for event
for (i = 0; i<2; i++) // first time triggers with current state, so ignore
{
if ((n = epoll_wait(epfd, &events, 1, -1)) == -1)
{
gpio_event_remove(gpio);
return 5;
}
}
if (n > 0)
{
lseek(events.data.fd, 0, SEEK_SET);
if (lseek(events.data.fd, 0, SEEK_SET) < 0)
{
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: could not seek GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
return 6;
}
if (read(events.data.fd, &buf, sizeof(buf)) != 1)
{
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: could not read GPIO %d (%s)", gpio, strerror(errno));
add_error_msg(err);
gpio_event_remove(gpio);
return 6;
}
if (events.data.fd != fd)
{
char err[80];
snprintf(err, sizeof(err), "blocking_wait_for_edge: events.data.fd (%d) not equal to fd (%d) for GPIO %d", events.data.fd, fd, gpio);
add_error_msg(err);
gpio_event_remove(gpio);
return 7;
}

View File

@ -54,21 +54,21 @@ SOFTWARE.
#define PUD_DOWN 1
#define PUD_UP 2
int gpio_export(unsigned int gpio);
int gpio_unexport(unsigned int gpio);
int gpio_export(int gpio);
int gpio_unexport(int gpio);
void exports_cleanup(void);
int gpio_set_direction(unsigned int gpio, unsigned int in_flag);
int gpio_get_direction(unsigned int gpio, unsigned int *value);
int gpio_set_value(unsigned int gpio, unsigned int value);
int gpio_get_value(unsigned int gpio, unsigned int *value);
int gpio_set_direction(int gpio, unsigned int in_flag);
int gpio_get_direction(int gpio, unsigned int *value);
int gpio_set_value(int gpio, unsigned int value);
int gpio_get_value(int gpio, unsigned int *value);
int add_edge_detect(unsigned int gpio, unsigned int edge);
void remove_edge_detect(unsigned int gpio);
int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio));
int event_detected(unsigned int gpio);
int gpio_event_add(unsigned int gpio);
int gpio_event_remove(unsigned int gpio);
int gpio_is_evented(unsigned int gpio);
int add_edge_detect(int gpio, unsigned int edge);
void remove_edge_detect(int gpio);
int add_edge_callback(int gpio, void (*func)(int gpio));
int event_detected(int gpio);
int gpio_event_add(int gpio);
int gpio_event_remove(int gpio);
int gpio_is_evented(int gpio);
int event_initialise(void);
void event_cleanup(void);
int blocking_wait_for_edge(unsigned int gpio, unsigned int edge);
int blocking_wait_for_edge(int gpio, unsigned int edge);

View File

@ -45,12 +45,12 @@ SOFTWARE.
static int gpio_warnings = 1;
int max_gpio = -1;
void *gpio_direction = NULL;
dyn_int_array_t *gpio_direction = NULL;
struct py_callback
{
char channel[32];
unsigned int gpio;
int gpio;
PyObject *py_cb;
unsigned long long lastcall;
unsigned int bouncetime;
@ -74,6 +74,8 @@ static void remember_gpio_direction(int gpio, int direction)
// python function cleanup()
static PyObject *py_cleanup(PyObject *self, PyObject *args)
{
clear_error_msg();
// clean up any exports
event_cleanup();
@ -83,13 +85,15 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args)
// python function setup(channel, direction, pull_up_down=PUD_OFF, initial=None)
static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwargs)
{
unsigned int gpio;
int gpio;
char *channel;
int direction;
int pud = PUD_OFF;
int initial = 0;
static char *kwlist[] = {"channel", "direction", "pull_up_down", "initial", NULL};
clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|ii", kwlist, &channel, &direction, &pud, &initial))
return NULL;
@ -113,39 +117,54 @@ static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwar
return NULL;
}
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid value for channel");
if (get_gpio_number(channel, &gpio) < 0) {
char err[2000];
snprintf(err, sizeof(err), "Invalid channel %s. (%s)", channel, get_error_msg());
PyErr_SetString(PyExc_ValueError, err);
return NULL;
}
int result = gpio_export(gpio);
if (result < 0) {
PyErr_SetString(PyExc_ValueError, "Channel in use (already exported)");
if (gpio_export(gpio) < 0) {
char err[2000];
snprintf(err, sizeof(err), "Error setting up channel %s, maybe already exported? (%s)", channel, get_error_msg());
PyErr_SetString(PyExc_RuntimeError, err);
return NULL;
}
if (gpio_set_direction(gpio, direction) < 0) {
char err[2000];
snprintf(err, sizeof(err), "Error setting direction %d on channel %s. (%s)", direction, channel, get_error_msg());
PyErr_SetString(PyExc_RuntimeError, err);
return NULL;
}
gpio_set_direction(gpio, direction);
// For some reason, the following code doesn't work for XIOs. Skip.
if (direction == OUTPUT) {
gpio_set_value(gpio, initial);
if (gpio_set_value(gpio, initial) < 0) {
char err[2000];
snprintf(err, sizeof(err), "Error setting initial value %d on channel %s. (%s)", initial, channel, get_error_msg());
PyErr_SetString(PyExc_RuntimeError, err);
return NULL;
}
}
remember_gpio_direction(gpio, direction);
Py_RETURN_NONE;
}
} /* py_setup_channel */
// python function output(channel, value)
static PyObject *py_output_gpio(PyObject *self, PyObject *args)
{
unsigned int gpio;
int gpio;
int value;
char *channel;
clear_error_msg();
if (!PyArg_ParseTuple(args, "si", &channel, &value))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -157,26 +176,31 @@ static PyObject *py_output_gpio(PyObject *self, PyObject *args)
int result = gpio_set_value(gpio, value);
if (result < 0) {
PyErr_SetString(PyExc_RuntimeError, "Could not write to channel");
char err[2000];
snprintf(err, sizeof(err), "Could no write %d on channel %s. (%s)", value, channel, get_error_msg());
PyErr_SetString(PyExc_RuntimeError, err);
return NULL;
}
Py_RETURN_NONE;
}
} /* py_output_gpio */
// python function value = input(channel)
static PyObject *py_input_gpio(PyObject *self, PyObject *args)
{
unsigned int gpio;
int gpio;
char *channel;
unsigned int value;
PyObject *py_value;
clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -194,7 +218,7 @@ static PyObject *py_input_gpio(PyObject *self, PyObject *args)
return py_value;
}
static void run_py_callbacks(unsigned int gpio)
static void run_py_callbacks(int gpio)
{
PyObject *result;
PyGILState_STATE gstate;
@ -202,6 +226,8 @@ static void run_py_callbacks(unsigned int gpio)
struct timeval tv_timenow;
unsigned long long timenow;
clear_error_msg();
while (cb != NULL)
{
if (cb->gpio == gpio)
@ -231,11 +257,13 @@ static void run_py_callbacks(unsigned int gpio)
}
}
static int add_py_callback(char *channel, unsigned int gpio, unsigned int bouncetime, PyObject *cb_func)
static int add_py_callback(char *channel, int gpio, unsigned int bouncetime, PyObject *cb_func)
{
struct py_callback *new_py_cb;
struct py_callback *cb = py_callbacks;
clear_error_msg();
// add callback to py_callbacks list
new_py_cb = malloc(sizeof(struct py_callback));
if (new_py_cb == 0)
@ -266,12 +294,14 @@ static int add_py_callback(char *channel, unsigned int gpio, unsigned int bounce
// python function add_event_callback(gpio, callback, bouncetime=0)
static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject *kwargs)
{
unsigned int gpio;
int gpio;
char *channel;
unsigned int bouncetime = 0;
PyObject *cb_func;
char *kwlist[] = {"gpio", "callback", "bouncetime", NULL};
clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|i", kwlist, &channel, &cb_func, &bouncetime))
return NULL;
@ -282,7 +312,7 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
}
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -290,7 +320,7 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
if (gpio != lookup_gpio_by_name("AP-EINT3")
&& gpio != lookup_gpio_by_name("AP-EINT1")
&& !(gpio >= lookup_gpio_by_name("XIO-P0") && gpio <= lookup_gpio_by_name("XIO-P7"))) {
PyErr_SetString(PyExc_RuntimeError, "Callbacks currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
PyErr_SetString(PyExc_ValueError, "Callbacks currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
return NULL;
}
@ -315,13 +345,15 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
// python function add_event_detect(gpio, edge, callback=None, bouncetime=0
static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *kwargs)
{
unsigned int gpio;
int gpio;
char *channel;
int edge, result;
unsigned int bouncetime = 0;
PyObject *cb_func = NULL;
char *kwlist[] = {"gpio", "edge", "callback", "bouncetime", NULL};
clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|Oi", kwlist, &channel, &edge, &cb_func, &bouncetime))
return NULL;
@ -332,7 +364,7 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
}
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -340,14 +372,7 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
if (gpio != lookup_gpio_by_name("AP-EINT3")
&& gpio != lookup_gpio_by_name("AP-EINT1")
&& !(gpio >= lookup_gpio_by_name("XIO-P0") && gpio <= lookup_gpio_by_name("XIO-P7"))) {
PyErr_SetString(PyExc_RuntimeError, "Edge Detection currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
return NULL;
}
// check channel is set up as an input
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
PyErr_SetString(PyExc_ValueError, "Edge Detection currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
return NULL;
}
@ -358,6 +383,13 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
return NULL;
}
// check channel is set up as an input
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
return NULL;
}
if ((result = add_edge_detect(gpio, edge)) != 0) // starts a thread
{
if (result == 1)
@ -380,17 +412,19 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
// python function remove_event_detect(gpio)
static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
{
unsigned int gpio;
int gpio;
char *channel;
struct py_callback *cb = py_callbacks;
struct py_callback *temp;
struct py_callback *prev = NULL;
clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -398,7 +432,7 @@ static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
if (gpio != lookup_gpio_by_name("AP-EINT3")
&& gpio != lookup_gpio_by_name("AP-EINT1")
&& !(gpio >= lookup_gpio_by_name("XIO-P0") && gpio <= lookup_gpio_by_name("XIO-P7"))) {
PyErr_SetString(PyExc_RuntimeError, "Edge Detection currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
PyErr_SetString(PyExc_ValueError, "Edge Detection currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
return NULL;
}
@ -429,14 +463,16 @@ static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
// python function value = event_detected(channel)
static PyObject *py_event_detected(PyObject *self, PyObject *args)
{
unsigned int gpio;
int gpio;
char *channel;
clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -449,16 +485,18 @@ static PyObject *py_event_detected(PyObject *self, PyObject *args)
// python function py_wait_for_edge(gpio, edge)
static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
{
unsigned int gpio;
int gpio;
int edge, result;
char *channel;
char error[81];
clear_error_msg();
if (!PyArg_ParseTuple(args, "si", &channel, &edge))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -466,14 +504,7 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
if (gpio != lookup_gpio_by_name("AP-EINT3")
&& gpio != lookup_gpio_by_name("AP-EINT1")
&& !(gpio >= lookup_gpio_by_name("XIO-P0") && gpio <= lookup_gpio_by_name("XIO-P7"))) {
PyErr_SetString(PyExc_RuntimeError, "Edge Detection currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
return NULL;
}
// check channel is setup as an input
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
PyErr_SetString(PyExc_ValueError, "Edge Detection currently available on AP-EINT1, AP-EINT3, and XIO-P0 to XIO-P7 only");
return NULL;
}
@ -484,6 +515,13 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
return NULL;
}
// check channel is setup as an input
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
return NULL;
}
Py_BEGIN_ALLOW_THREADS // disable GIL
result = blocking_wait_for_edge(gpio, edge);
Py_END_ALLOW_THREADS // enable GIL
@ -506,17 +544,18 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
// python function value = gpio_function(gpio)
static PyObject *py_gpio_function(PyObject *self, PyObject *args)
{
unsigned int gpio;
int gpio;
unsigned int value;
PyObject *func;
char *channel;
clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
PyErr_SetString(PyExc_ValueError, "Invalid channel");
return NULL;
}
@ -534,6 +573,8 @@ static PyObject *py_gpio_function(PyObject *self, PyObject *args)
// python function setwarnings(state)
static PyObject *py_setwarnings(PyObject *self, PyObject *args)
{
clear_error_msg();
if (!PyArg_ParseTuple(args, "i", &gpio_warnings))
return NULL;
@ -552,56 +593,62 @@ static PyObject *py_gpio_base(PyObject *self, PyObject *args)
unsigned int value;
PyObject *py_value;
value = get_xio_base();
clear_error_msg();
value = get_xio_base();
if (value <= 0) {
char err[1024];
snprintf(err, sizeof(err), "Could not get XIO base ('%s')", get_error_msg());
PyErr_SetString(PyExc_RuntimeError, err);
return NULL;
}
py_value = Py_BuildValue("i", value);
return py_value;
}
// Internal unit tests
extern int num_get_xio_base;
extern pins_t pins_info[];
static PyObject *py_selftest(PyObject *self, PyObject *args)
{
int input;
clear_error_msg();
if (!PyArg_ParseTuple(args, "i", &input))
return NULL;
printf("Testing get_xio_base\n");
ASSRT(num_get_xio_base == 0);
int base = get_xio_base(); ASSRT(base > 0 && base < 1024);
ASSRT(num_get_xio_base == 1);
int second_base = get_xio_base(); ASSRT(second_base == base);
ASSRT(num_get_xio_base == 1); /* make sure it didn't do the full calc a second time. */
printf("base=%d\n", base);
int first_base = get_xio_base(); ASSRT(first_base > 0);
int second_base = get_xio_base(); ASSRT(second_base == first_base);
printf("base=%d\n", first_base);
printf("Testing lookup_gpio_by_key\n");
ASSRT(0 == lookup_gpio_by_key("U13_1"));
ASSRT(-1 == lookup_gpio_by_key("U13_1"));
ASSRT(48 == lookup_gpio_by_key("U13_9"));
ASSRT(47 == lookup_gpio_by_key("U13_11"));
ASSRT(base == lookup_gpio_by_key("U14_13"));
ASSRT((base+1) == lookup_gpio_by_key("U14_14"));
ASSRT((base+6) == lookup_gpio_by_key("U14_19"));
ASSRT((base+7) == lookup_gpio_by_key("U14_20"));
ASSRT(first_base == lookup_gpio_by_key("U14_13"));
ASSRT((first_base+1) == lookup_gpio_by_key("U14_14"));
ASSRT((first_base+6) == lookup_gpio_by_key("U14_19"));
ASSRT((first_base+7) == lookup_gpio_by_key("U14_20"));
ASSRT(193 == lookup_gpio_by_key("U14_23"));
ASSRT(139 == lookup_gpio_by_key("U14_38"));
ASSRT(0 == lookup_gpio_by_key("U14_40"));
ASSRT(0 == lookup_gpio_by_key("NOTFOUND"));
ASSRT(0 == lookup_gpio_by_key("U14_"));
ASSRT(0 == lookup_gpio_by_key("U14_4000"));
ASSRT(-1 == lookup_gpio_by_key("U14_40"));
ASSRT(-1 == lookup_gpio_by_key("NOTFOUND"));
ASSRT(-1 == lookup_gpio_by_key("U14_"));
ASSRT(-1 == lookup_gpio_by_key("U14_4000"));
printf("Testing lookup_gpio_by_name\n");
ASSRT(0 == lookup_gpio_by_name("GND"));
ASSRT(-1 == lookup_gpio_by_name("GND"));
ASSRT(48 == lookup_gpio_by_name("TWI1-SDA"));
ASSRT(47 == lookup_gpio_by_name("TWI1-SCK"));
ASSRT(base == lookup_gpio_by_name("XIO-P0"));
ASSRT((base+6) == lookup_gpio_by_name("XIO-P6"));
ASSRT((base+7) == lookup_gpio_by_name("XIO-P7"));
ASSRT(first_base == lookup_gpio_by_name("XIO-P0"));
ASSRT((first_base+6) == lookup_gpio_by_name("XIO-P6"));
ASSRT((first_base+7) == lookup_gpio_by_name("XIO-P7"));
ASSRT(139 == lookup_gpio_by_name("CSID7"));
ASSRT(0 == lookup_gpio_by_name("NOTFOUND"));
ASSRT(0 == lookup_gpio_by_name("CSID"));
ASSRT(0 == lookup_gpio_by_name("CSID777"));
ASSRT(-1 == lookup_gpio_by_name("NOTFOUND"));
ASSRT(-1 == lookup_gpio_by_name("CSID"));
ASSRT(-1 == lookup_gpio_by_name("CSID777"));
printf("Testing lookup_ain_by_key\n");
ASSRT(-1 == lookup_ain_by_key("U14_1"));
@ -661,6 +708,26 @@ static PyObject *py_selftest(PyObject *self, PyObject *args)
ASSRT(2 == get_spi_bus_path_number(0)); /* doesn't really work on CHIP */
ASSRT(2 == get_spi_bus_path_number(1)); /* doesn't really work on CHIP */
printf("Testing error message buffer\n");
clear_error_msg();
ASSRT(0 == strlen(get_error_msg()));
char *s100 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
add_error_msg(s100); ASSRT(100 == strlen(get_error_msg()));
// Subsequent messages added include a newline separator.
add_error_msg(s100); add_error_msg(s100); add_error_msg(s100); ASSRT(403 == strlen(get_error_msg()));
add_error_msg(s100); add_error_msg(s100); add_error_msg(s100); ASSRT(706 == strlen(get_error_msg()));
add_error_msg(s100); add_error_msg(s100); add_error_msg(s100); ASSRT(1009 == strlen(get_error_msg()));
add_error_msg(s100); add_error_msg(s100); add_error_msg(s100); ASSRT(1023 == strlen(get_error_msg()));
printf("Testing dynamic integer array\n");
dyn_int_array_t *my_array = NULL;
ASSRT(-2 == dyn_int_array_get(&my_array, 29, -2)); ASSRT(my_array->num_elements == 45);
dyn_int_array_set(&my_array, 44, 3, -2); ASSRT(my_array->num_elements == 45);
ASSRT(3 == dyn_int_array_get(&my_array, 44, -2)); ASSRT(my_array->num_elements == 45);
dyn_int_array_set(&my_array, 45, 6, -2); ASSRT(my_array->num_elements == 69);
ASSRT(6 == dyn_int_array_get(&my_array, 45, -2)); ASSRT(my_array->num_elements == 69);
dyn_int_array_delete(&my_array);
int value = input;
PyObject *py_value = Py_BuildValue("i", value);
@ -704,6 +771,8 @@ PyMODINIT_FUNC initGPIO(void)
{
PyObject *module = NULL;
clear_error_msg();
#if PY_MAJOR_VERSION > 2
if ((module = PyModule_Create(&rpigpiomodule)) == NULL)
return NULL;

View File

@ -0,0 +1,96 @@
# The default ``config.py``
def set_prefs(prefs):
"""This function is called before opening the project"""
# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = [
'*.pyc', '*~', '.ropeproject', '.hg', '.svn', '_svn', '.git',
'.tox', '.env', 'node_modules', 'bower_components']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
#prefs['python_files'] = ['*.py']
# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
#prefs.add('source_folders', 'src')
# You can extend python path for looking up modules
#prefs.add('python_path', '~/python/')
# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False
# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0
# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True
# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True
# How many undos to hold?
prefs['max_history_items'] = 32
# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False
# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4
# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []
# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True
# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False
# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False
# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False
# If `True`, rope will sort imports alphabetically by module name
# instead of alphabetically by import statement, with from imports
# after normal imports.
prefs['sort_imports_alphabetically'] = False
def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!

View File

@ -0,0 +1,2 @@
<EFBFBD>}q(Utest_softpwm_setup]q(Uteardown_moduleqUTestSoftpwmSetupqeUtest_gpio_output]q(hUTestGPIOOutputqeUtest_pwm_setup]q(hU TestPwmSetupqeUtest_gpio_setup]q (hU TestSetupq
eUtest_gpio_input]q (hU

View File

@ -0,0 +1 @@
<EFBFBD>]q(]q]qe.

View File

@ -0,0 +1 @@
<EFBFBD>}q.

View File

@ -42,7 +42,7 @@ if (GPIO.input("XIO-P0") != GPIO.HIGH):
num_errs += 1
GPIO.cleanup()
GPIO.setup("XIO-P0", GPIO.IN)
GPIO.setup("U14_13", GPIO.IN) # XIO-P0
GPIO.setup("CSID0", GPIO.OUT, initial=GPIO.LOW)
if (GPIO.input("XIO-P0") != GPIO.LOW):
print "A low output on CSI0 does not lead to a low input on XIO-P0."
@ -51,7 +51,7 @@ if (GPIO.input("XIO-P0") != GPIO.LOW):
GPIO.cleanup()
GPIO.setup("XIO-P0", GPIO.IN)
GPIO.setup("CSID0", GPIO.OUT)
GPIO.setup("U14_31", GPIO.OUT) # CSID0
# VERIFY SIMPLE FUNCTIONALITY
print "VERIFY SIMPLE FUNCTIONALITY"
@ -66,7 +66,7 @@ assert(GPIO.input("XIO-P0") == GPIO.LOW)
# ==============================================
# EDGE DETECTION - AP-EINT1
print "SETTING UP EDGE DETECTION ON AP-EINT1"
print "SETTING UP RISING EDGE DETECTION ON AP-EINT1"
GPIO.setup("AP-EINT1", GPIO.IN)
print "adding event detect"
GPIO.add_event_detect("AP-EINT1", GPIO.RISING)
@ -75,13 +75,12 @@ print "VERIFYING EDGE DETECT"
f = open("/sys/class/gpio/gpio193/edge", "r")
edge = f.read()
f.close()
print "edge='", edge, "'"
assert(edge == "rising\n")
GPIO.remove_event_detect("AP-EINT1")
# ==============================================
# EDGE DETECTION - AP-EINT3
print "SETTING UP EDGE DETECTION ON AP-EINT3"
print "SETTING UP BOTH EDGE DETECTION ON AP-EINT3"
GPIO.setup("AP-EINT3", GPIO.IN)
GPIO.add_event_detect("AP-EINT3", GPIO.BOTH)
@ -89,13 +88,12 @@ print "VERIFYING EDGE DETECT"
f = open("/sys/class/gpio/gpio35/edge", "r")
edge = f.read()
f.close()
print "EDGE: %s" % edge
assert(edge == "both\n")
GPIO.remove_event_detect("AP-EINT3")
# ==============================================
# EDGE DETECTION - EXPANDED GPIO
print "SETTING UP EDGE DETECTION ON XIO-P0"
print "SETTING UP FALLING EDGE DETECTION ON XIO-P0"
GPIO.add_event_detect("XIO-P0", GPIO.FALLING, myfuncallback)
print "VERIFYING EDGE DETECT"
@ -104,7 +102,6 @@ gfile = "/sys/class/gpio/gpio%d/edge" % base
f = open(gfile, "r")
edge = f.read()
f.close()
print "EDGE: %s" % edge
assert(edge == "falling\n")
# LOOP WRITING ON CSID0 TO HOPEFULLY GET CALLBACK TO WORK
@ -134,14 +131,60 @@ GPIO.setup("CSID1", GPIO.IN)
try:
GPIO.add_event_detect("CSID1", GPIO.FALLING, myfuncallback)
print "Oops, it did not throw an exception! BUG!!!"
except:
num_errors += 1
except ValueError, ex:
print "error msg=", ex.args[0]
pass
except RuntimeError, ex:
print "error msg=", ex.args[0]
pass
print "TESTING ERRORS THROWN WHEN SETTING UP AN ALREADY EXPORTED GPIO"
try:
GPIO.output("XIO-P0", GPIO.LOW)
print "Oops, it did not throw an exception! BUG!!!"
num_errors += 1
except ValueError, ex:
print "error msg=", ex.args[0]
pass
except RuntimeError, ex:
print "error msg=", ex.args[0]
pass
print "TESTING ERRORS THROWN WHEN WRITING TO A GPIO WITH NO DIRECTION"
try:
GPIO.output("CSID1", GPIO.LOW)
print "Oops, it did not throw an exception! BUG!!!"
except:
num_errors += 1
except ValueError, ex:
print "error msg=", ex.args[0]
pass
except RuntimeError, ex:
print "error msg=", ex.args[0]
pass
print "TESTING ERRORS THROWN FOR ILLEGAL GPIO"
try:
GPIO.setup("NOTUSED", GPIO.IN)
print "Oops, it did not throw an exception! BUG!!!"
num_errors += 1
except ValueError, ex:
print "error msg=", ex.args[0]
pass
except RuntimeError, ex:
print "error msg=", ex.args[0]
pass
print "TESTING ERRORS THROWN FOR NON-GPIO"
try:
GPIO.setup("FEL", GPIO.IN)
print "Oops, it did not throw an exception! BUG!!!"
num_errors += 1
except ValueError, ex:
print "error msg=", ex.args[0]
pass
except RuntimeError, ex:
print "error msg=", ex.args[0]
pass
print "CLEANUP"