From 8e4a809f1214f93ab78442f8a95216cf2e4a1067 Mon Sep 17 00:00:00 2001 From: Henry Bruce Date: Mon, 14 Dec 2015 11:50:30 -0800 Subject: [PATCH] iio: C API changes and C++ API enhancements - C API read/write integer functions changed to int to match C types - C API now has close function to release resources acquired during init - iio internal type isr_event() function now has args param in signature - C++ API now supports events with handler interface and new data structure - C and C++ examples updated to use API changes Signed-off-by: Henry Bruce Signed-off-by: Brendan Le Foll --- api/mraa/iio.h | 10 ++-- api/mraa/iio.hpp | 108 ++++++++++++++++++++++++++++++---- examples/c++/Iio-dummy.cpp | 77 +++++++++++++++++++++--- examples/iio_driver.c | 12 ++-- include/mraa_internal_types.h | 2 +- src/iio/iio.c | 19 +++--- 6 files changed, 186 insertions(+), 42 deletions(-) diff --git a/api/mraa/iio.h b/api/mraa/iio.h index 77b6728..eadbab9 100644 --- a/api/mraa/iio.h +++ b/api/mraa/iio.h @@ -93,13 +93,13 @@ int mraa_iio_get_channel_count(mraa_iio_context dev); mraa_result_t mraa_iio_read_float(mraa_iio_context dev, const char* filename, float* data); -mraa_result_t mraa_iio_read_integer(mraa_iio_context dev, const char* filename, int* data); +mraa_result_t mraa_iio_read_int(mraa_iio_context dev, const char* filename, int* data); -mraa_result_t mraa_iio_read_string(mraa_iio_context dev, const char* filename, char* data); +mraa_result_t mraa_iio_read_string(mraa_iio_context dev, const char* filename, char* data, int max_len); mraa_result_t mraa_iio_write_float(mraa_iio_context dev, const char* attr_chan, const float data); -mraa_result_t mraa_iio_write_integer(mraa_iio_context dev, const char* attr_chan, const int data); +mraa_result_t mraa_iio_write_int(mraa_iio_context dev, const char* attr_chan, const int data); mraa_result_t mraa_iio_write_string(mraa_iio_context dev, const char* attr_chan, const char* data); @@ -110,7 +110,7 @@ mraa_result_t mraa_iio_get_event_data(mraa_iio_context dev); mraa_result_t mraa_iio_event_poll(mraa_iio_context dev, struct iio_event_data* data); mraa_result_t -mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data), void* args); +mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data, void* args), void* args); mraa_result_t mraa_iio_event_extract_event(struct iio_event_data* event, int* chan_type, @@ -132,7 +132,7 @@ mraa_result_t mraa_iio_update_channels(mraa_iio_context dev); * @param dev The iio context * @return Result of operation */ -mraa_result_t mraa_iio_stop(mraa_iio_context dev); +mraa_result_t mraa_iio_close(mraa_iio_context dev); #ifdef __cplusplus } diff --git a/api/mraa/iio.hpp b/api/mraa/iio.hpp index 60d9440..35951ed 100644 --- a/api/mraa/iio.hpp +++ b/api/mraa/iio.hpp @@ -32,6 +32,24 @@ namespace mraa { +struct IioEventData +{ + int channelType; + int modifier; + int type; + int direction; + int channel; + int channel2; + int diff; +}; + +class IioHandler +{ +public: + virtual void onIioEvent(const IioEventData& eventData) = 0; +}; + + /** * @brief API to Industrial IO * @@ -44,7 +62,7 @@ class Iio public: /** * Iio Constructor, takes a device number which will map directly to sysfs - * e.g. device 0 mAps to /sys/bus/iio/devices/iio:device0 + * e.g. device 0 maps to /sys/bus/iio/devices/iio:device0 * * @param device IIO device number * @@ -60,12 +78,34 @@ class Iio } } + /** + * Iio Constructor + * + * @param deviceName IIO device name + * + * @throws std::invalid_argument if initialization fails + */ + Iio(const std::string& deviceName) + { + std::ostringstream oss; + int id = mraa_iio_get_device_num_by_name(deviceName.c_str()); + if (id == -1) { + oss << "IIO device name " << deviceName << " not found"; + throw std::invalid_argument(oss.str()); + } + m_iio = mraa_iio_init(id); + if (m_iio == NULL) { + oss << "IIO device " << deviceName << " is not valid"; + throw std::invalid_argument(oss.str()); + } + } + /** * Iio destructor */ ~Iio() { - mraa_iio_stop(m_iio); + mraa_iio_close(m_iio); } @@ -75,23 +115,25 @@ class Iio * @returns The device name */ std::string - getDeviceName() + getDeviceName() const { return mraa_iio_get_device_name(m_iio); } /** - * Read an integer value from specified attribute. + * Read an int value from specified attribute. * - * @returns The integer value + * @param attributeName attribute mame + * + * @returns The int value * * @throws std::invalid_argument if read fails */ int - readInt(const std::string& attributeName) + readInt(const std::string& attributeName) const { int value; - mraa_result_t res = mraa_iio_read_integer(m_iio, attributeName.c_str(), &value); + mraa_result_t res = mraa_iio_read_int(m_iio, attributeName.c_str(), &value); if (res != MRAA_SUCCESS) { std::ostringstream oss; oss << "IIO readInt for attibute " << attributeName << " failed"; @@ -103,12 +145,14 @@ class Iio /** * Read a float value from specified attribute. * + * @param attributeName attribute mame + * * @returns The float value * * @throws std::invalid_argument if read fails */ float - readFloat(const std::string& attributeName) + readFloat(const std::string& attributeName) const { float value; mraa_result_t res = mraa_iio_read_float(m_iio, attributeName.c_str(), &value); @@ -121,14 +165,17 @@ class Iio } /** - * Write an integer value to specified attribute. + * Write an int value to specified attribute. + * + * @param attributeName attribute mame + * @param value int value * * @throws std::invalid_argument if write fails */ void - writeInt(const std::string& attributeName, int value) + writeInt(const std::string& attributeName, int value) const { - mraa_result_t res = mraa_iio_write_integer(m_iio, attributeName.c_str(), value); + mraa_result_t res = mraa_iio_write_int(m_iio, attributeName.c_str(), value); if (res != MRAA_SUCCESS) { std::ostringstream oss; oss << "IIO writeInt for attibute " << attributeName << " failed"; @@ -140,10 +187,13 @@ class Iio /** * Write a float value to specified attribute. * + * @param attributeName attribute mame + * @param value float value + * * @throws std::invalid_argument if write fails */ void - writeFloat(const std::string& attributeName, float value) + writeFloat(const std::string& attributeName, float value) const { mraa_result_t res = mraa_iio_write_float(m_iio, attributeName.c_str(), value); if (res != MRAA_SUCCESS) { @@ -154,8 +204,42 @@ class Iio } + /** + * Register event handler. + * + * @param handler handler class that implements IioHandler + * + * @throws std::invalid_argument on failure + */ + void + registerEventHandler(IioHandler* handler) const + { + mraa_result_t res = mraa_iio_event_setup_callback(m_iio, private_event_handler, handler); + if (res != MRAA_SUCCESS) { + throw std::runtime_error("registerEventHandler failed"); + } + } private: + static void private_event_handler(iio_event_data* data, void *args) + { + if (args != NULL) { + IioHandler* handler = (IioHandler*)args; + IioEventData eventData; + int chan_type, modifier, type, direction, channel, channel2, different; + mraa_iio_event_extract_event(data, &chan_type, &modifier, &type, &direction, &channel, &channel2, &different); + eventData.channelType = chan_type; + eventData.modifier = modifier; + eventData.type = type; + eventData.direction = direction; + eventData.channel = channel; + eventData.channel2 = channel2; + eventData.diff = different; + handler->onIioEvent(eventData); + } + } + mraa_iio_context m_iio; }; + } diff --git a/examples/c++/Iio-dummy.cpp b/examples/c++/Iio-dummy.cpp index 62d48f7..70e1128 100644 --- a/examples/c++/Iio-dummy.cpp +++ b/examples/c++/Iio-dummy.cpp @@ -22,7 +22,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// #include +#include #include #include #include @@ -31,6 +31,18 @@ #define EXPECT_FAILURE 0 #define EXPECT_SUCCESS 1 +#define IIO_TRY(func) \ +{ \ + bool success = true; \ + try { \ + iio_device->func; \ + } catch (std::exception& e) { \ + success = false; \ + } \ + log_result(#func, "", true, success); \ +} + +// Macro to run IIO method on attribute and log output #define IIO_RUN(func, attr, value, expect) \ { \ std::string attr_name = attr; \ @@ -43,6 +55,7 @@ log_result(#func, attr_name, expect, success); \ } +// Macro to run IIO method on attribute and check for expected result and log output #define IIO_TEST(func, attr, value, expect) \ { \ std::string attr_name = attr; \ @@ -56,7 +69,9 @@ } mraa::Iio* iio_device; +int eventCount = 0; +// Log result of test. Note a "fail" (i.e. success is false) will be displayed as a pass if a fail was expected void log_result(std::string test_name, std::string attr_name, bool expect_success, bool success) { std::string result; @@ -64,35 +79,79 @@ void log_result(std::string test_name, std::string attr_name, bool expect_succes result = success ? "PASS" : "FAIL"; else result = success ? "FAIL" : "PASS"; - fprintf(stdout, "%s(%s): %s\n", test_name.c_str(), attr_name.c_str(), result.c_str()); + if (attr_name.empty()) + fprintf(stdout, "%s: %s\n", test_name.c_str(), result.c_str()); + else + fprintf(stdout, "%s(%s): %s\n", test_name.c_str(), attr_name.c_str(), result.c_str()); } +// Generate iio_dummy driver event by writing a string to a specific sysfs node +bool generate_event() +{ + FILE *fp = fopen("/sys/bus/iio/devices/iio_evgen/poke_ev0", "w"); + if (fp == NULL) + return false; + fprintf(fp, "1\n"); + fclose(fp); + return true; +} + + +// IIO event handler that checks for event from dummy_iio_evgen driver +class IioTestHandler : public mraa::IioHandler +{ +protected: + void onIioEvent(const mraa::IioEventData& eventData) { + if (eventData.channelType == IIO_VOLTAGE && eventData.direction == IIO_EV_DIR_RISING && eventData.type == IIO_EV_TYPE_THRESH) + eventCount++; + } +}; int main() { + IioTestHandler testHandler; + std::string deviceName; try { - iio_device = new mraa::Iio(0); + mraa::Iio* iio_device0 = new mraa::Iio(0); + std::cout << "IIO device 0 found by id." << std::endl; + deviceName = iio_device0->getDeviceName(); + delete iio_device0; } catch (std::exception& e) { - std::cerr << "IIO device 0 not found" << std::endl; + std::cerr << "IIO device 0 not found." << std::endl; return EXIT_FAILURE; } try { - mraa::Iio* bad_iio_device = new mraa::Iio(1); - delete bad_iio_device; + mraa::Iio* iio_device1 = new mraa::Iio(1); + delete iio_device1; } catch (std::exception& e) { - std::cerr << "IIO device 1 not found" << std::endl; + std::cerr << "IIO device 1 not found. This is expected behavior." << std::endl; } + try { + iio_device = new mraa::Iio(deviceName); + std::cout << "IIO device 0 found by name." << std::endl; + } catch (std::exception& e) { + std::cerr << "IIO device 0 not found." << std::endl; + return EXIT_FAILURE; + } + + std::cout << "Using IIO device0. Name is " << iio_device->getDeviceName() << std::endl; IIO_RUN(writeFloat, "in_accel_x_raw", 100, EXPECT_FAILURE); IIO_RUN(writeFloat, "in_voltage0_scale", 100, EXPECT_FAILURE); IIO_RUN(writeInt, "out_voltage0_raw", 100, EXPECT_SUCCESS); IIO_TEST(readInt, "in_accel_x_raw", 34, EXPECT_SUCCESS); - IIO_TEST(readFloat, "in_voltage0_scale", 0.001333, EXPECT_SUCCESS); - delete iio_device; + IIO_TEST(readFloat, "in_voltage0_scale", 0.001333, EXPECT_SUCCESS); + IIO_RUN(writeInt, "events/in_voltage0_thresh_rising_en", 1, EXPECT_SUCCESS); + IIO_TRY(registerEventHandler(&testHandler)); + eventCount = 0; + generate_event(); + usleep(500000); + log_result("eventReceived", "", (eventCount == 1), true); + delete iio_device; return EXIT_SUCCESS; } diff --git a/examples/iio_driver.c b/examples/iio_driver.c index a8369a9..824e0b1 100644 --- a/examples/iio_driver.c +++ b/examples/iio_driver.c @@ -93,7 +93,7 @@ main() } float iio_float; - int iio_integer; + int iio_int; mraa_result_t ret; ret = mraa_iio_write_float(iio_device0, "in_accel_scale", 0.019163); @@ -106,14 +106,14 @@ main() fprintf(stdout, "IIO read %f\n", iio_float); } - ret = mraa_iio_write_integer(iio_device0, "scan_elements/in_accel_x_en", 1); + ret = mraa_iio_write_int(iio_device0, "scan_elements/in_accel_x_en", 1); if (ret == MRAA_SUCCESS) { - fprintf(stdout, "IIO write success\n", iio_integer); + fprintf(stdout, "IIO write success\n"); } - ret = mraa_iio_read_integer(iio_device0, "scan_elements/in_accel_x_en", &iio_integer); + ret = mraa_iio_read_int(iio_device0, "scan_elements/in_accel_x_en", &iio_int); if (ret == MRAA_SUCCESS) { - fprintf(stdout, "IIO read %d\n", iio_integer); + fprintf(stdout, "IIO read %d\n", iio_int); } if (mraa_iio_trigger_buffer(iio_device0, interrupt, NULL) == MRAA_SUCCESS) { @@ -127,7 +127,7 @@ main() if (iio_device6 == NULL) { return EXIT_FAILURE; } - mraa_iio_write_integer(iio_device6, "events/in_proximity2_thresh_either_en", 1); + mraa_iio_write_int(iio_device6, "events/in_proximity2_thresh_either_en", 1); // Blocking until event fired diff --git a/include/mraa_internal_types.h b/include/mraa_internal_types.h index 70d4197..1c76e33 100755 --- a/include/mraa_internal_types.h +++ b/include/mraa_internal_types.h @@ -139,7 +139,7 @@ struct _iio { int fp_event; /**< event file descriptor for IIO device */ void (* isr)(char* data); /**< the interupt service request */ void *isr_args; /**< args return when interupt service request triggered */ - void (* isr_event)(struct iio_event_data* data); /**< the event interupt service request */ + void (* isr_event)(struct iio_event_data* data, void* args); /**< the event interupt service request */ int chan_num; pthread_t thread_id; /**< the isr handler thread id */ mraa_iio_channel* channels; diff --git a/src/iio/iio.c b/src/iio/iio.c index 221eec6..da6dc59 100644 --- a/src/iio/iio.c +++ b/src/iio/iio.c @@ -209,7 +209,7 @@ mraa_result_t mraa_iio_read_float(mraa_iio_context dev, const char* attr_name, float* data) { char buf[MAX_SIZE]; - mraa_result_t result = mraa_iio_read_string(dev, attr_name, buf); + mraa_result_t result = mraa_iio_read_string(dev, attr_name, buf, MAX_SIZE-1); if (result != MRAA_SUCCESS) return result; int status = sscanf(buf, "%f", data); @@ -219,10 +219,10 @@ mraa_iio_read_float(mraa_iio_context dev, const char* attr_name, float* data) mraa_result_t -mraa_iio_read_integer(mraa_iio_context dev, const char* attr_name, int* data) +mraa_iio_read_int(mraa_iio_context dev, const char* attr_name, int* data) { char buf[MAX_SIZE]; - mraa_result_t result = mraa_iio_read_string(dev, attr_name, buf); + mraa_result_t result = mraa_iio_read_string(dev, attr_name, buf, MAX_SIZE-1); if (result != MRAA_SUCCESS) return result; int status = sscanf(buf, "%d", data); @@ -231,14 +231,14 @@ mraa_iio_read_integer(mraa_iio_context dev, const char* attr_name, int* data) } mraa_result_t -mraa_iio_read_string(mraa_iio_context dev, const char* attr_name, char* data) +mraa_iio_read_string(mraa_iio_context dev, const char* attr_name, char* data, int max_len) { char buf[MAX_SIZE]; mraa_result_t result = MRAA_ERROR_UNSPECIFIED; snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, attr_name); int fd = open(buf, O_RDONLY); if (fd != -1) { - ssize_t len = read(fd, data, MAX_SIZE); + ssize_t len = read(fd, data, max_len); if (len > 0) result = MRAA_SUCCESS; close(fd); @@ -256,7 +256,7 @@ mraa_iio_write_float(mraa_iio_context dev, const char* attr_name, const float da } mraa_result_t -mraa_iio_write_integer(mraa_iio_context dev, const char* attr_name, const int data) +mraa_iio_write_int(mraa_iio_context dev, const char* attr_name, const int data) { char buf[MAX_SIZE]; snprintf(buf, MAX_SIZE, "%d", data); @@ -454,7 +454,7 @@ mraa_iio_event_handler(void* arg) for (;;) { if (mraa_iio_event_poll_nonblock(dev->fp_event, &data) == MRAA_SUCCESS) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - dev->isr_event(&data); + dev->isr_event(&data, dev->isr_args); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } else { // we must have got an error code so die nicely @@ -465,7 +465,7 @@ mraa_iio_event_handler(void* arg) } mraa_result_t -mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data), void* args) +mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data, void* args), void* args) { int ret; char bu[MAX_SIZE]; @@ -486,6 +486,7 @@ mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_even } dev->isr_event = fptr; + dev->isr_args = args; pthread_create(&dev->thread_id, NULL, mraa_iio_event_handler, (void*) dev); return MRAA_SUCCESS; @@ -607,7 +608,7 @@ mraa_iio_update_channels(mraa_iio_context dev) } mraa_result_t -mraa_iio_stop(mraa_iio_context dev) +mraa_iio_close(mraa_iio_context dev) { free(dev->channels); return MRAA_SUCCESS;