From d0ea43f8d16249bc9af23ef2d200440c3bedef7c Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Fri, 27 Jun 2014 15:37:48 +0100 Subject: [PATCH] mraa: initial implementation of "hooks" * Should allow for more platform quirks to be handled by mraa without * massive conditional areas per platform. Signed-off-by: Thomas Ingleby --- docs/platform-hooks.md | 21 +++++++++++ include/intel_galileo_rev_d.h | 4 +- include/intel_galileo_rev_g.h | 4 +- include/mraa_adv_func.h | 66 +++++++++++++++++++++++++++++++++ include/mraa_internal.h | 8 ++++ include/mraa_internal_types.h | 48 ++++++++++++++++++++++++ src/gpio/gpio.c | 69 +++++++++++++++++++++++++---------- src/intel_galileo_rev_d.c | 2 +- src/intel_galileo_rev_g.c | 2 +- src/mraa.c | 13 +++++-- 10 files changed, 209 insertions(+), 28 deletions(-) create mode 100644 docs/platform-hooks.md create mode 100644 include/mraa_adv_func.h create mode 100644 include/mraa_internal_types.h diff --git a/docs/platform-hooks.md b/docs/platform-hooks.md new file mode 100644 index 0000000..c66d9bf --- /dev/null +++ b/docs/platform-hooks.md @@ -0,0 +1,21 @@ +Hooks can be defined per supported platform to allow for highly custom operations if needed. +This feature of MRAA should only be used by developers defining the board definitions, NOT an end user. + +## Types of Hooks + +** REPLACE ** +Defining a replace function will entirely replace the associate function. This should only be done if your new function can handle everything the mraa function would normally. + +** PRE ** +Any functionality defined here will be performed when the main function is called. + +** POST ** +Any functionality perfomed here is done just before the normal function returns. All post functions will have passed into them the return value that would normally be returned. + +## Hooks +** gpio ** +* init (pre-post) - On RAW functions +* mode (replace-pre-post) +* dir (replace-pre-post) +* write (pre-post) +* use-mmaped (replace-pre-post) diff --git a/include/intel_galileo_rev_d.h b/include/intel_galileo_rev_d.h index 95ec144..d1ff21d 100644 --- a/include/intel_galileo_rev_d.h +++ b/include/intel_galileo_rev_d.h @@ -24,9 +24,9 @@ #pragma once -#include "mraa.h" +#include "mraa_adv_func.h" #define MRAA_INTEL_GALILEO_REV_D_PINCOUNT 25 mraa_board_t* -mraa_intel_galileo_rev_d(); +mraa_intel_galileo_rev_d(mraa_adv_func* adv); diff --git a/include/intel_galileo_rev_g.h b/include/intel_galileo_rev_g.h index 2550beb..478b178 100644 --- a/include/intel_galileo_rev_g.h +++ b/include/intel_galileo_rev_g.h @@ -24,7 +24,9 @@ #pragma once +#include "mraa_adv_func.h" + #define MRAA_INTEL_GALILEO_GEN_2_PINCOUNT 25 mraa_board_t* -mraa_intel_galileo_gen2(); +mraa_intel_galileo_gen2(mraa_adv_func* adv); diff --git a/include/mraa_adv_func.h b/include/mraa_adv_func.h new file mode 100644 index 0000000..6a71125 --- /dev/null +++ b/include/mraa_adv_func.h @@ -0,0 +1,66 @@ +/* + * Author: Thomas Ingleby + * Copyright (c) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "common.h" +#include "mraa.h" +#include "types.h" + +typedef struct { + mraa_boolean_t gpio_init_pre:1; + mraa_boolean_t gpio_init_post:1; + mraa_boolean_t gpio_mode_replace:1; + mraa_boolean_t gpio_mode_pre:1; + mraa_boolean_t gpio_mode_post:1; + mraa_boolean_t gpio_dir_replace:1; + mraa_boolean_t gpio_dir_pre:1; + mraa_boolean_t gpio_dir_post:1; + mraa_boolean_t gpio_write_pre:1; + mraa_boolean_t gpio_write_post:1; + mraa_boolean_t gpio_mmaped_write_replace:1; + mraa_boolean_t gpio_mmaped_write_pre:1; + mraa_boolean_t gpio_mmaped_write_post:1; +} mraa_adv_def_t; + +typedef struct { + mraa_adv_def_t defined; + int (*gpio_init_pre) (int pin); + void (*gpio_init_post) (mraa_gpio_context dev); + + mraa_result_t (*gpio_mode_replace) (mraa_gpio_context dev, gpio_mode_t mode); + mraa_result_t (*gpio_mode_pre) (mraa_gpio_context dev, gpio_mode_t mode); + mraa_result_t (*gpio_mode_post) (mraa_gpio_context dev, gpio_mode_t mode); + + mraa_result_t (*gpio_dir_replace) (mraa_gpio_context dev, gpio_dir_t dir); + mraa_result_t (*gpio_dir_pre) (mraa_gpio_context dev, gpio_dir_t dir); + mraa_result_t (*gpio_dir_post) (mraa_gpio_context dev, gpio_dir_t dir); + + mraa_result_t (*gpio_write_pre) (mraa_gpio_context dev, int value); + mraa_result_t (*gpio_write_post) (mraa_gpio_context dev, int value); + + mraa_result_t (*gpio_mmaped_write_replace) (mraa_gpio_context dev, int value); + mraa_result_t (*gpio_mmaped_write_pre) (mraa_gpio_context dev, int value); + mraa_result_t (*gpio_mmaped_write_post) (mraa_gpio_context dev, int value); +} mraa_adv_func; diff --git a/include/mraa_internal.h b/include/mraa_internal.h index e8a24fb..536c2eb 100644 --- a/include/mraa_internal.h +++ b/include/mraa_internal.h @@ -25,6 +25,8 @@ #pragma once #include "common.h" +#include "mraa_adv_func.h" +#include "mraa_internal_types.h" /** Setup gpio * @@ -76,3 +78,9 @@ mraa_mmap_pin_t* mraa_setup_mmap_gpio(int pin); * @return out direction to setup. 1 for output 0 for input */ mraa_result_t mraa_swap_complex_gpio(int pin, int out); + +/** Get the advance structure. + * + * @return struct containing internal advance information for hooks + */ +mraa_adv_func* mraa_get_advance(); diff --git a/include/mraa_internal_types.h b/include/mraa_internal_types.h new file mode 100644 index 0000000..133291e --- /dev/null +++ b/include/mraa_internal_types.h @@ -0,0 +1,48 @@ +/* + * Author: Thomas Ingleby + * Author: Brendan Le Foll + * Copyright (c) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "common.h" + +/** + * A structure representing a gpio pin. + */ +struct _gpio { + /*@{*/ + int pin; /**< the pin number, as known to the os. */ + int phy_pin; /**< pin passed to clean init. -1 none and raw*/ + int value_fp; /**< the file pointer to the value of the gpio */ + void (* isr)(void *); /**< the interupt service request */ + void *isr_args; /**< args return when interupt service request triggered */ + pthread_t thread_id; /**< the isr handler thread id */ + int isr_value_fp; /**< the isr file pointer on the value */ + mraa_boolean_t owner; /**< If this context originally exported the pin */ + mraa_boolean_t mmap; + void *reg; + unsigned int reg_sz; + unsigned int reg_bit_pos; + /*@}*/ +}; diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index c0ed21d..b929375 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -39,26 +39,7 @@ #define MAX_SIZE 64 #define POLL_TIMEOUT -/** - * A structure representing a gpio pin. - */ - -struct _gpio { - /*@{*/ - int pin; /**< the pin number, as known to the os. */ - int phy_pin; /**< pin passed to clean init. -1 none and raw*/ - int value_fp; /**< the file pointer to the value of the gpio */ - void (* isr)(void *); /**< the interupt service request */ - void *isr_args; /**< args return when interupt service request triggered */ - pthread_t thread_id; /**< the isr handler thread id */ - int isr_value_fp; /**< the isr file pointer on the value */ - mraa_boolean_t owner; /**< If this context originally exported the pin */ - mraa_boolean_t mmap; - void *reg; - unsigned int reg_sz; - unsigned int reg_bit_pos; - /*@}*/ -}; +static mraa_adv_func* advance; static mraa_result_t mraa_gpio_get_valfp(mraa_gpio_context dev) @@ -88,6 +69,13 @@ mraa_gpio_init(int pin) mraa_gpio_context mraa_gpio_init_raw(int pin) { + advance = mraa_get_advance(); + if (advance->defined.gpio_init_pre) { + if((advance->gpio_init_pre(pin)) != 0) { + printf("MRAA: Error in pre hook\n"); + return NULL; + } + } if (pin < 0) return NULL; @@ -122,17 +110,30 @@ mraa_gpio_init_raw(int pin) dev->owner = 1; close(export); } + + if (advance->defined.gpio_init_post) + advance->gpio_init_post(dev); return dev; } static mraa_result_t mraa_gpio_write_register(mraa_gpio_context dev,int value) { + if (advance->defined.gpio_mmaped_write_replace) + return advance->gpio_mmaped_write_replace(dev,value); + if (advance->defined.gpio_mmaped_write_pre) { + mraa_result_t pre_ret = (advance->gpio_mmaped_write_pre(dev,value)); + if(pre_ret != MRAA_SUCCESS) + return pre_ret; + } if (value == 1) { *((unsigned *)dev->reg) |= (1<reg_bit_pos); return MRAA_SUCCESS; } *((unsigned *)dev->reg) &= ~(1<reg_bit_pos); + + if (advance->defined.gpio_mmaped_write_post) + return advance->gpio_mmaped_write_post(dev,value); return MRAA_SUCCESS; } @@ -319,6 +320,15 @@ mraa_gpio_isr_exit(mraa_gpio_context dev) mraa_result_t mraa_gpio_mode(mraa_gpio_context dev, gpio_mode_t mode) { + if (advance->defined.gpio_mode_replace) + return advance->gpio_mode_replace(dev,mode); + + if (advance->defined.gpio_mode_pre) { + mraa_result_t pre_ret = (advance->gpio_mode_pre(dev,mode)); + if(pre_ret != MRAA_SUCCESS) + return pre_ret; + } + if (dev->value_fp != -1) { close(dev->value_fp); dev->value_fp = -1; @@ -360,12 +370,21 @@ mraa_gpio_mode(mraa_gpio_context dev, gpio_mode_t mode) } close(drive); + if (advance->defined.gpio_mode_post) + return advance->gpio_mode_post(dev,mode); return MRAA_SUCCESS; } mraa_result_t mraa_gpio_dir(mraa_gpio_context dev, gpio_dir_t dir) { + if (advance->defined.gpio_dir_replace) + return advance->gpio_dir_replace(dev,dir); + if (advance->defined.gpio_dir_pre) { + mraa_result_t pre_ret = (advance->gpio_dir_pre(dev,dir)); + if(pre_ret != MRAA_SUCCESS) + return pre_ret; + } if (dev == NULL) { return MRAA_ERROR_INVALID_HANDLE; } @@ -410,6 +429,8 @@ mraa_gpio_dir(mraa_gpio_context dev, gpio_dir_t dir) } close(direction); + if (advance->defined.gpio_dir_post) + return advance->gpio_dir_post(dev,dir); return MRAA_SUCCESS; } @@ -441,6 +462,12 @@ mraa_gpio_write(mraa_gpio_context dev, int value) if (dev->mmap == 1) return mraa_gpio_write_register(dev,value); + if (advance->defined.gpio_write_pre) { + mraa_result_t pre_ret = (advance->gpio_write_pre(dev,value)); + if(pre_ret != MRAA_SUCCESS) + return pre_ret; + } + if (dev->value_fp == -1) { mraa_gpio_get_valfp(dev); } @@ -454,6 +481,8 @@ mraa_gpio_write(mraa_gpio_context dev, int value) return MRAA_ERROR_INVALID_HANDLE; } + if (advance->defined.gpio_write_post) + return advance->gpio_write_post(dev,value); return MRAA_SUCCESS; } diff --git a/src/intel_galileo_rev_d.c b/src/intel_galileo_rev_d.c index a8a8e83..38d6950 100644 --- a/src/intel_galileo_rev_d.c +++ b/src/intel_galileo_rev_d.c @@ -29,7 +29,7 @@ #include "intel_galileo_rev_d.h" mraa_board_t* -mraa_intel_galileo_rev_d() +mraa_intel_galileo_rev_d(mraa_adv_func* adv) { mraa_board_t* b = (mraa_board_t*) malloc(sizeof(mraa_board_t)); if (b == NULL) diff --git a/src/intel_galileo_rev_g.c b/src/intel_galileo_rev_g.c index a87e4be..925a8df 100644 --- a/src/intel_galileo_rev_g.c +++ b/src/intel_galileo_rev_g.c @@ -30,7 +30,7 @@ #include "intel_galileo_rev_g.h" mraa_board_t* -mraa_intel_galileo_gen2() +mraa_intel_galileo_gen2(mraa_adv_func* adv) { mraa_board_t* b = (mraa_board_t*) malloc(sizeof(mraa_board_t)); if (b == NULL) diff --git a/src/mraa.c b/src/mraa.c index 24651ee..09f3c65 100644 --- a/src/mraa.c +++ b/src/mraa.c @@ -37,6 +37,7 @@ //static mraa_pininfo_t* pindata; static mraa_board_t* plat = NULL; static mraa_platform_t platform_type = MRAA_UNKNOWN_PLATFORM; +static mraa_adv_func* advance = NULL; const char * mraa_get_version() @@ -81,15 +82,16 @@ mraa_init() free(line); fclose(fh); + advance = (mraa_adv_func*) malloc(sizeof(mraa_adv_func)); switch(platform_type) { case MRAA_INTEL_GALILEO_GEN2: - plat = mraa_intel_galileo_gen2(); + plat = mraa_intel_galileo_gen2(advance); break; case MRAA_INTEL_GALILEO_GEN1: - plat = mraa_intel_galileo_rev_d(); + plat = mraa_intel_galileo_rev_d(advance); break; default: - plat = mraa_intel_galileo_rev_d(); + plat = mraa_intel_galileo_rev_d(advance); fprintf(stderr, "Platform not found, initialising MRAA_INTEL_GALILEO_GEN1\n"); } @@ -443,3 +445,8 @@ mraa_adc_supported_bits() return plat->adc_supported; } + +mraa_adv_func* +mraa_get_advance() { + return advance; +}