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);
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,
* @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
}
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
*
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
*
}
/**
+ * 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);
}
* @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.
+ *
+ * @param attributeName attribute mame
*
- * @returns The integer value
+ * @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";
/**
* 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);
}
/**
- * 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";
/**
* 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) {
}
+ /**
+ * 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;
};
+
}
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-// #include <unistd.h>
+#include <unistd.h>
#include <iostream>
#include <math.h>
#include <float.h>
#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; \
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; \
}
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;
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;
}
}
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);
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) {
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
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;
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);
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);
}
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);
}
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);
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
}
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];
}
dev->isr_event = fptr;
+ dev->isr_args = args;
pthread_create(&dev->thread_id, NULL, mraa_iio_event_handler, (void*) dev);
return MRAA_SUCCESS;
}
mraa_result_t
-mraa_iio_stop(mraa_iio_context dev)
+mraa_iio_close(mraa_iio_context dev)
{
free(dev->channels);
return MRAA_SUCCESS;