Private
Public Access
2
0

gpio: chardev interface / multiple gpio support for sysfs

Signed-off-by: Mihai Stefanescu <mihai.t.gh.stefanescu@gmail.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
mihais
2017-09-23 17:13:06 +03:00
committed by Brendan Le Foll
parent fbc2ad6045
commit 2b98fc7869
7 changed files with 887 additions and 764 deletions

View File

@@ -104,6 +104,15 @@ typedef enum {
MRAA_GPIO_PUSH_PULL = 1, /**< Push Pull Configuration */
} mraa_gpio_out_driver_mode_t;
typedef long long unsigned int mraa_timestamp_t;
typedef struct {
int id;
mraa_timestamp_t timestamp;
} mraa_gpio_event;
typedef mraa_gpio_event* mraa_gpio_events_t;
/**
* Initialise gpio_context, based on board number
*
@@ -112,7 +121,15 @@ typedef enum {
*/
mraa_gpio_context mraa_gpio_init(int pin);
mraa_gpio_context mraa_gpio_init_multiple(int pins[], int num_pins);
/**
* Initialise gpio_context, based on board number, for multiple pins (can be one).
*
* @param pins Pin array read from the board
* @param num_pins Number of pins - must be the same as the pins array length provided
* as the first argument.
* @returns gpio context or NULL
*/
mraa_gpio_context mraa_gpio_init_multi(int pins[], int num_pins);
/**
* Initialise gpio context without any mapping to a pin
@@ -131,13 +148,11 @@ mraa_gpio_context mraa_gpio_init_raw(int gpiopin);
*/
mraa_result_t mraa_gpio_edge_mode(mraa_gpio_context dev, mraa_gpio_edge_t mode);
mraa_result_t mraa_gpio_edge_mode_multiple(mraa_gpio_context dev, mraa_gpio_edge_t mode);
/**
* Set an interrupt on pin
* Set an interrupt on pin(s).
*
* @param dev The Gpio context
* @param edge The edge mode to set the gpio into
* @param edge The edge mode to set the gpio(s) into
* @param fptr Function pointer to function to be called when interrupt is
* triggered
* @param args Arguments passed to the interrupt handler (fptr)
@@ -145,11 +160,19 @@ mraa_result_t mraa_gpio_edge_mode_multiple(mraa_gpio_context dev, mraa_gpio_edge
*/
mraa_result_t mraa_gpio_isr(mraa_gpio_context dev, mraa_gpio_edge_t edge, void (*fptr)(void*), void* args);
mraa_result_t mraa_gpio_isr_multiple(mraa_gpio_context dev, mraa_gpio_edge_t edge, void (*fptr)(void*), void* args);
/**
* Get an array of structures describing triggered events.
*
* @param dev The Gpio context
* @return Array of structures containing pairs of pin id's and the associated timestamp.
* An event with negative id value indicates that no event was triggered for the respective pin.
* The array length is that of the number of pins provided in mraa_gpio_init_multi().
*/
mraa_gpio_events_t mraa_gpio_get_events(mraa_gpio_context dev);
/**
* Stop the current interrupt watcher on this Gpio, and set the Gpio edge mode
* to MRAA_GPIO_EDGE_NONE
* to MRAA_GPIO_EDGE_NONE(only for sysfs interface).
*
* @param dev The Gpio context
* @return Result of operation
@@ -157,37 +180,36 @@ mraa_result_t mraa_gpio_isr_multiple(mraa_gpio_context dev, mraa_gpio_edge_t edg
mraa_result_t mraa_gpio_isr_exit(mraa_gpio_context dev);
/**
* Set Gpio Output Mode,
* Set Gpio(s) Output Mode,
*
* @param dev The Gpio context
* @param mode The Gpio Output Mode
* @param mode The Gpio(s) Output Mode
* @return Result of operation
*/
mraa_result_t mraa_gpio_mode(mraa_gpio_context dev, mraa_gpio_mode_t mode);
/**
* Set Gpio direction
* Set Gpio(s) direction
*
* @param dev The Gpio context
* @param dir The direction of the Gpio
* @param dir The direction of the Gpio(s)
* @return Result of operation
*/
mraa_result_t mraa_gpio_dir(mraa_gpio_context dev, mraa_gpio_dir_t dir);
mraa_result_t mraa_gpio_dir_multiple(mraa_gpio_context dev, mraa_gpio_dir_t dir);
/**
* Read Gpio direction
* Read Gpio(s) direction
*
* @param dev The Gpio context
* @param dir The address where to store the Gpio direction
* @param dir The address where to store the Gpio(s) direction
* @return Result of operation
*/
mraa_result_t mraa_gpio_read_dir(mraa_gpio_context dev, mraa_gpio_dir_t *dir);
/**
* Close the Gpio context
* - Will free the memory for the context and unexport the Gpio
* - Will free the memory for the context and unexport the Gpio - sysfs interface.
* - Will free up the memory used by context and close related file descriptors - chardev interface.
*
* @param dev The Gpio context
* @return Result of operation
@@ -203,10 +225,15 @@ mraa_result_t mraa_gpio_close(mraa_gpio_context dev);
*/
int mraa_gpio_read(mraa_gpio_context dev);
/* Values array is provided by user. Must be the same size as the array passed in init.
* It will be overwritten with the read results.
/**
* Read the Gpio(s) value. The user must provide an integer array with a length equal to the
* number of pins provided to mraa_gpio_init_multi() function.
*
* @param dev The Gpio context
* @param output_values The array provided by the user. Existing values will be overwritten with the newly read ones.
* @return Result of operation
*/
mraa_result_t mraa_gpio_read_multiple(mraa_gpio_context dev, int output_values[]);
mraa_result_t mraa_gpio_read_multi(mraa_gpio_context dev, int output_values[]);
/**
* Write to the Gpio Value.
@@ -217,7 +244,16 @@ mraa_result_t mraa_gpio_read_multiple(mraa_gpio_context dev, int output_values[]
*/
mraa_result_t mraa_gpio_write(mraa_gpio_context dev, int value);
mraa_result_t mraa_gpio_write_multiple(mraa_gpio_context dev, int input_values[]);
/**
* Write to the Gpio(s) Value. The user must provide an integer array with a length equal to the
* number of pins provided to mraa_gpio_init_multi() function.
*
* @param dev The Gpio context
* @param output_values The array provided by the user. It must contain the values intended to be written
* to the gpio pins, in the same order as the init function.
* @return Result of operation
*/
mraa_result_t mraa_gpio_write_multi(mraa_gpio_context dev, int input_values[]);
/**
* Change ownership of the context.

103
examples/gpio_multiple_rw.c Normal file
View File

@@ -0,0 +1,103 @@
/* This currently works only on Intel Joule Platform. */
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "mraa/gpio.h"
int running = 0;
void
sig_handler(int signo)
{
if (signo == SIGINT) {
printf("Closing down nicely\n");
running = -1;
}
}
int main(int argc, char** argv)
{
mraa_result_t r = MRAA_SUCCESS;
/* These are Joule's onboard LED's. */
int default_joule_leds[] = {100, 101, 102, 103};
int *gpio_pins;
int num_pins;
int *input_values, *output_values;
printf("Provide int arg(s) if you want to toggle gpio pins other than Joule's onboard LED's\n");
if (argc < 2) {
gpio_pins = default_joule_leds;
num_pins = 4;
} else {
num_pins = argc - 1;
gpio_pins = malloc(num_pins * sizeof(int));
for (int i = 0; i < num_pins; ++i) {
gpio_pins[i] = strtol(argv[i+1], NULL, 10);
}
}
/* Allocate input and output values arrays. */
input_values = malloc(num_pins * sizeof(int));
output_values = malloc(num_pins * sizeof(int));
mraa_init();
fprintf(stdout, "MRAA Version: %s\nStarting program...\n", mraa_get_version());
mraa_gpio_context gpio = mraa_gpio_init_multi(gpio_pins, num_pins);
if (gpio == NULL) {
fprintf(stderr, "Error during gpio initialization\n");
exit(1);
}
r = mraa_gpio_dir(gpio, MRAA_GPIO_OUT);
if (r != MRAA_SUCCESS) {
mraa_result_print(r);
}
signal(SIGINT, sig_handler);
/* Set input values first. */
memset(input_values, 0, num_pins * sizeof(int));
while (running == 0) {
r = mraa_gpio_write_multi(gpio, input_values);
sleep(1);
if (r != MRAA_SUCCESS) {
mraa_result_print(r);
} else {
r = mraa_gpio_read_multi(gpio, output_values);
if (r != MRAA_SUCCESS) {
mraa_result_print(r);
}
}
for (int i = 0; i < num_pins; ++i) {
input_values[i] = (input_values[i] + 1) % 2;
}
}
memset(input_values, 0, num_pins * sizeof(int));
mraa_gpio_write_multi(gpio, input_values);
r = mraa_gpio_close(gpio);
if (r != MRAA_SUCCESS) {
mraa_result_print(r);
}
/* Cleanup. */
if (argc >= 2) {
free(gpio_pins);
}
free(input_values);
free(output_values);
return r;
}

View File

@@ -29,6 +29,7 @@ extern "C" {
#endif
#include "mraa_internal.h"
#include "linux/gpio.h"
typedef struct {
int chip_fd;
@@ -38,6 +39,8 @@ typedef struct {
typedef struct gpioline_info mraa_gpiod_line_info;
void _mraa_free_gpio_groups(mraa_gpio_context dev);
void _mraa_close_gpio_event_handles(mraa_gpio_context dev);
void _mraa_close_gpio_desc(mraa_gpio_context dev);
int _mraa_gpiod_ioctl(int fd, unsigned long gpio_request, void* data);
mraa_gpiod_chip_info* mraa_get_chip_info_by_path(const char* path);
@@ -45,6 +48,7 @@ mraa_gpiod_chip_info* mraa_get_chip_info_by_name(const char* name);
mraa_gpiod_chip_info* mraa_get_chip_info_by_label(const char* label);
mraa_gpiod_chip_info* mraa_get_chip_info_by_number(unsigned number);
mraa_gpiod_line_info* mraa_get_line_info_from_descriptor(int chip_fd, unsigned line_number);
mraa_gpiod_line_info* mraa_get_line_info_by_chip_number(unsigned chip_number, unsigned line_number);
mraa_gpiod_line_info* mraa_get_line_info_by_chip_name(const char* chip_name, unsigned line_number);
mraa_gpiod_line_info* mraa_get_line_info_by_chip_label(const char* chip_label, unsigned line_number);
@@ -52,8 +56,14 @@ mraa_gpiod_line_info* mraa_get_line_info_by_chip_label(const char* chip_label, u
int mraa_get_lines_handle(int chip_fd, unsigned line_offsets[], unsigned num_lines, unsigned flags, unsigned default_value);
int mraa_set_line_values(int line_handle, unsigned int num_lines, unsigned char input_values[]);
int mraa_get_line_values(int line_handle, unsigned int num_lines, unsigned char output_values[]);
int mraa_get_number_of_gpio_chips();
mraa_boolean_t mraa_is_gpio_line_kernel_owned(mraa_gpiod_line_info *linfo);
mraa_boolean_t mraa_is_gpio_line_dir_out(mraa_gpiod_line_info *linfo);
mraa_boolean_t mraa_is_gpio_line_active_low(mraa_gpiod_line_info *linfo);
mraa_boolean_t mraa_is_gpio_line_open_drain(mraa_gpiod_line_info *linfo);
mraa_boolean_t mraa_is_gpio_line_open_source(mraa_gpiod_line_info *linfo);
int mraa_get_number_of_gpio_chips();
/* Multiple gpio support. */
typedef struct _gpio_group* mraa_gpiod_group_t;

View File

@@ -155,18 +155,12 @@ struct _gpio {
AGpio *bgpio;
#endif
/* TODO: The below members should be integrated in gpio_group struct. */
int dev_fd;
int gpiod_handle;
unsigned int gpio_chip;
unsigned int gpio_line;
/* Multiple gpio support. These members are treated separately for now until multiple gpio support is accepted. */
unsigned int num_chips;
struct _gpio_group *gpio_group;
/* Pin index passed by the user to gpio_group structures. */
unsigned int num_chips;
int *pin_to_gpio_table;
unsigned int num_pins;
mraa_gpio_events_t events;
int *provided_pins;
struct _gpio *next;
};

File diff suppressed because it is too large Load Diff

View File

@@ -50,38 +50,74 @@
void
_mraa_free_gpio_groups(mraa_gpio_context dev)
{
mraa_gpiod_group_t gpio_group = dev->gpio_group;
mraa_gpiod_group_t gpio_iter;
for (int i = 0; i < dev->num_chips; ++i) {
if (gpio_group[i].is_required) {
free(gpio_group[i].gpio_lines);
free(gpio_group[i].rw_values);
free(gpio_group[i].gpio_group_to_pins_table);
for_each_gpio_group(gpio_iter, dev) {
free(gpio_iter->gpio_lines);
free(gpio_iter->rw_values);
free(gpio_iter->gpio_group_to_pins_table);
if (gpio_group[i].gpiod_handle != -1) {
close(gpio_group[i].gpiod_handle);
if (gpio_iter->gpiod_handle != -1) {
close(gpio_iter->gpiod_handle);
}
if (gpio_group[i].event_handles != NULL) {
for (int j = 0; j < gpio_group[i].num_gpio_lines; ++j) {
close(gpio_group[i].event_handles[j]);
if (gpio_iter->event_handles != NULL) {
for (int j = 0; j < gpio_iter->num_gpio_lines; ++j) {
close(gpio_iter->event_handles[j]);
}
free(gpio_group[i].event_handles);
free(gpio_iter->event_handles);
}
close(gpio_group[i].dev_fd);
}
close(gpio_iter->dev_fd);
}
free(gpio_group);
free(dev->gpio_group);
/* Also delete the pin to gpio chip mapping. */
free(dev->pin_to_gpio_table);
/* User provided array saved internally. */
free(dev->provided_pins);
/* Finally, delete event array. */
free(dev->events);
}
void
_mraa_close_gpio_event_handles(mraa_gpio_context dev)
{
mraa_gpiod_group_t gpio_iter;
for_each_gpio_group(gpio_iter, dev) {
if (gpio_iter->event_handles != NULL) {
for (int j = 0; j < gpio_iter->num_gpio_lines; ++j) {
close(gpio_iter->event_handles[j]);
}
free(gpio_iter->event_handles);
/* In the end, _mraa_free_gpio_groups will be called. */
gpio_iter->event_handles = NULL;
}
}
}
void
_mraa_close_gpio_desc(mraa_gpio_context dev)
{
mraa_gpiod_group_t gpio_iter;
for_each_gpio_group(gpio_iter, dev) {
if (gpio_iter->gpiod_handle != -1) {
close(gpio_iter->gpiod_handle);
gpio_iter->gpiod_handle = -1;
}
}
}
int
_mraa__mraa_gpiod_ioctl(int fd, unsigned long gpio_request, void* data)
_mraa_gpiod_ioctl(int fd, unsigned long gpio_request, void* data)
{
int status;
@@ -319,6 +355,37 @@ mraa_get_line_values(int line_handle, unsigned int num_lines, unsigned char outp
return status;
}
mraa_boolean_t
mraa_is_gpio_line_kernel_owned(mraa_gpiod_line_info *linfo)
{
return (linfo->flags & GPIOLINE_FLAG_IS_OUT);
}
mraa_boolean_t
mraa_is_gpio_line_dir_out(mraa_gpiod_line_info *linfo)
{
return (linfo->flags & GPIOLINE_FLAG_IS_OUT);
}
mraa_boolean_t
mraa_is_gpio_line_active_low(mraa_gpiod_line_info *linfo)
{
return (linfo->flags & GPIOLINE_FLAG_ACTIVE_LOW);
}
mraa_boolean_t
mraa_is_gpio_line_open_drain(mraa_gpiod_line_info *linfo)
{
return (linfo->flags & GPIOLINE_FLAG_OPEN_DRAIN);
}
mraa_boolean_t
mraa_is_gpio_line_open_source(mraa_gpiod_line_info *linfo)
{
return (linfo->flags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
}
int
mraa_get_number_of_gpio_chips()
{
@@ -343,4 +410,3 @@ mraa_get_number_of_gpio_chips()
/* Assume opendir() error. */
return num_chips;
}

View File

@@ -57,6 +57,7 @@
#include "firmata/firmata_mraa.h"
#include "grovepi/grovepi.h"
#include "gpio.h"
#include "gpio/gpio_chardev.h"
#include "version.h"
#include "i2c.h"
#include "pwm.h"
@@ -100,43 +101,7 @@ mraa_set_log_level(int level)
mraa_boolean_t mraa_is_kernel_chardev_interface_compatible()
{
struct utsname buf;
int status;
status = uname(&buf);
if (status) {
syslog(LOG_ERR, "uname() error");
return 0;
}
int major, minor;
char *token;
token = strtok(buf.release, ".");
if (token == NULL) {
syslog(LOG_ERR, "Could not find kernel version major number");
return 0;
}
status = mraa_atoi(token, &major);
if (status) {
syslog(LOG_ERR, "mraa_atoi() error");
return 0;
}
token = strtok(NULL, ".");
if (token == NULL) {
syslog(LOG_ERR, "Could not find kernel version minor number");
return 0;
}
status = mraa_atoi(token, &minor);
if (status) {
syslog(LOG_ERR, "mraa_atoi() error");
return 0;
}
if (major < 4 || minor < 8) {
syslog(LOG_ERR, "Kernel version %i.%i not supported for chardev interface. Need version 4.8 or newer!", major, minor);
if (mraa_get_number_of_gpio_chips() <= 0) {
return 0;
}