iio: added event api
Signed-off-by: Lay, Kuan Loon <kuan.loon.lay@intel.com> Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
committed by
Brendan Le Foll
parent
e5f28ab04c
commit
4c41d2c2df
17
api/mraa/iio.h
Normal file → Executable file
17
api/mraa/iio.h
Normal file → Executable file
@@ -25,6 +25,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "iio_kernel_headers.h"
|
||||
|
||||
typedef struct {
|
||||
int index;
|
||||
@@ -40,6 +41,11 @@ typedef struct {
|
||||
unsigned int location;
|
||||
} mraa_iio_channel;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int enabled;
|
||||
} mraa_iio_event;
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief iio
|
||||
@@ -96,6 +102,17 @@ mraa_result_t mraa_iio_write(mraa_iio_context dev, const char* attribute);
|
||||
|
||||
mraa_result_t mraa_iio_get_channel_data(mraa_iio_context dev);
|
||||
|
||||
mraa_result_t mraa_iio_get_event_data(mraa_iio_context dev);
|
||||
|
||||
mraa_result_t mraa_iio_event_read(mraa_iio_context dev, const char* attribute, float* data);
|
||||
|
||||
mraa_result_t mraa_iio_event_write(mraa_iio_context dev, const char* attribute, 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_result_t mraa_iio_event_extract_event(struct iio_event_data* event, int* chan_type, int* modifier, int* type, int* direction, int* channel, int* channel2, int* different);
|
||||
/**
|
||||
* De-inits an mraa_iio_context device
|
||||
*
|
||||
|
||||
136
api/mraa/iio_kernel_headers.h
Executable file
136
api/mraa/iio_kernel_headers.h
Executable file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
|
||||
//For kernel 4.1+,
|
||||
//#include <linux/iio/types.h>
|
||||
//#include <linux/iio/events.h>
|
||||
|
||||
//linux/iio/types.h
|
||||
enum iio_chan_type {
|
||||
IIO_VOLTAGE,
|
||||
IIO_CURRENT,
|
||||
IIO_POWER,
|
||||
IIO_ACCEL,
|
||||
IIO_ANGL_VEL,
|
||||
IIO_MAGN,
|
||||
IIO_LIGHT,
|
||||
IIO_INTENSITY,
|
||||
IIO_PROXIMITY,
|
||||
IIO_TEMP,
|
||||
IIO_INCLI,
|
||||
IIO_ROT,
|
||||
IIO_ANGL,
|
||||
IIO_TIMESTAMP,
|
||||
IIO_CAPACITANCE,
|
||||
IIO_ALTVOLTAGE,
|
||||
IIO_CCT,
|
||||
IIO_PRESSURE,
|
||||
IIO_HUMIDITYRELATIVE,
|
||||
IIO_ACTIVITY,
|
||||
IIO_STEPS,
|
||||
IIO_ENERGY,
|
||||
IIO_DISTANCE,
|
||||
IIO_VELOCITY,
|
||||
};
|
||||
|
||||
enum iio_modifier {
|
||||
IIO_NO_MOD,
|
||||
IIO_MOD_X,
|
||||
IIO_MOD_Y,
|
||||
IIO_MOD_Z,
|
||||
IIO_MOD_X_AND_Y,
|
||||
IIO_MOD_X_AND_Z,
|
||||
IIO_MOD_Y_AND_Z,
|
||||
IIO_MOD_X_AND_Y_AND_Z,
|
||||
IIO_MOD_X_OR_Y,
|
||||
IIO_MOD_X_OR_Z,
|
||||
IIO_MOD_Y_OR_Z,
|
||||
IIO_MOD_X_OR_Y_OR_Z,
|
||||
IIO_MOD_LIGHT_BOTH,
|
||||
IIO_MOD_LIGHT_IR,
|
||||
IIO_MOD_ROOT_SUM_SQUARED_X_Y,
|
||||
IIO_MOD_SUM_SQUARED_X_Y_Z,
|
||||
IIO_MOD_LIGHT_CLEAR,
|
||||
IIO_MOD_LIGHT_RED,
|
||||
IIO_MOD_LIGHT_GREEN,
|
||||
IIO_MOD_LIGHT_BLUE,
|
||||
IIO_MOD_QUATERNION,
|
||||
IIO_MOD_TEMP_AMBIENT,
|
||||
IIO_MOD_TEMP_OBJECT,
|
||||
IIO_MOD_NORTH_MAGN,
|
||||
IIO_MOD_NORTH_TRUE,
|
||||
IIO_MOD_NORTH_MAGN_TILT_COMP,
|
||||
IIO_MOD_NORTH_TRUE_TILT_COMP,
|
||||
IIO_MOD_RUNNING,
|
||||
IIO_MOD_JOGGING,
|
||||
IIO_MOD_WALKING,
|
||||
IIO_MOD_STILL,
|
||||
IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z,
|
||||
};
|
||||
|
||||
enum iio_event_type {
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_TYPE_MAG,
|
||||
IIO_EV_TYPE_ROC,
|
||||
IIO_EV_TYPE_THRESH_ADAPTIVE,
|
||||
IIO_EV_TYPE_MAG_ADAPTIVE,
|
||||
IIO_EV_TYPE_CHANGE,
|
||||
};
|
||||
|
||||
enum iio_event_direction {
|
||||
IIO_EV_DIR_EITHER,
|
||||
IIO_EV_DIR_RISING,
|
||||
IIO_EV_DIR_FALLING,
|
||||
IIO_EV_DIR_NONE,
|
||||
};
|
||||
|
||||
//linux/iio/events.h
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/**
|
||||
* struct iio_event_data - The actual event being pushed to userspace
|
||||
* @id: event identifier
|
||||
* @timestamp: best estimate of time of event occurrence (often from
|
||||
* the interrupt handler)
|
||||
*/
|
||||
struct iio_event_data {
|
||||
unsigned long long int id;
|
||||
long long int timestamp;
|
||||
};
|
||||
|
||||
#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int)
|
||||
|
||||
#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
|
||||
|
||||
#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F)
|
||||
|
||||
#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
|
||||
|
||||
/* Event code number extraction depends on which type of event we have.
|
||||
* Perhaps review this function in the future*/
|
||||
#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((short int)(mask & 0xFFFF))
|
||||
#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((short int)(((mask) >> 16) & 0xFFFF))
|
||||
|
||||
#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF)
|
||||
#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1)
|
||||
34
examples/iio_driver.c
Normal file → Executable file
34
examples/iio_driver.c
Normal file → Executable file
@@ -47,6 +47,7 @@ printword(uint16_t input, mraa_iio_channel *chan)
|
||||
}
|
||||
|
||||
mraa_iio_context iio_device0;
|
||||
mraa_iio_context iio_device6;
|
||||
|
||||
void
|
||||
interrupt(char* data)
|
||||
@@ -65,6 +66,20 @@ interrupt(char* data)
|
||||
}
|
||||
}
|
||||
|
||||
void event_interrupt(struct iio_event_data* data)
|
||||
{
|
||||
int chan_type;
|
||||
int modifier;
|
||||
int type;
|
||||
int direction;
|
||||
int channel;
|
||||
int channel2;
|
||||
int different;
|
||||
mraa_iio_event_extract_event(data, &chan_type, &modifier, &type, &direction, &channel, &channel2, &different);
|
||||
|
||||
printf("event time %lld id %lld extracted chan_type %d modifier %d type %d direction %d channel %d channel2 %d different %d\n", data->timestamp, data->id, chan_type, modifier, type, direction, channel, channel2, different);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@@ -85,6 +100,25 @@ main()
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
struct iio_event_data event;
|
||||
iio_device6 = mraa_iio_init(6);
|
||||
if (iio_device6 == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
mraa_iio_event_write(iio_device6, "in_proximity2_thresh_either_en", "1");
|
||||
|
||||
|
||||
// Blocking until event fired
|
||||
if (mraa_iio_event_poll(iio_device6, &event) == MRAA_SUCCESS) {
|
||||
event_interrupt(&event); //just to show data
|
||||
}
|
||||
|
||||
if (mraa_iio_event_setup_callback(iio_device6, event_interrupt, NULL) == MRAA_SUCCESS) {
|
||||
sleep(100);
|
||||
return EXIT_SUCCESS;
|
||||
}*/
|
||||
|
||||
//! [Interesting]
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
4
include/mraa_internal_types.h
Normal file → Executable file
4
include/mraa_internal_types.h
Normal file → Executable file
@@ -136,11 +136,15 @@ struct _iio {
|
||||
int num; /**< IIO device number */
|
||||
char* name; /**< IIO device name */
|
||||
int fp; /**< IIO device in /dev */
|
||||
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 */
|
||||
int chan_num;
|
||||
pthread_t thread_id; /**< the isr handler thread id */
|
||||
mraa_iio_channel* channels;
|
||||
int event_num;
|
||||
mraa_iio_event* events;
|
||||
int datasize;
|
||||
};
|
||||
|
||||
|
||||
188
src/iio/iio.c
Normal file → Executable file
188
src/iio/iio.c
Normal file → Executable file
@@ -33,6 +33,7 @@
|
||||
#define IIO_SCAN_ELEM "scan_elements"
|
||||
#define IIO_SLASH_DEV "/dev/"IIO_DEVICE
|
||||
#define IIO_SYSFS_DEVICE "/sys/bus/iio/devices/"IIO_DEVICE
|
||||
#define IIO_EVENTS "events"
|
||||
|
||||
mraa_iio_context
|
||||
mraa_iio_init(int device)
|
||||
@@ -42,6 +43,8 @@ mraa_iio_init(int device)
|
||||
}
|
||||
|
||||
mraa_iio_get_channel_data(&plat_iio->iio_devices[device]);
|
||||
mraa_iio_get_event_data(&plat_iio->iio_devices[device]);
|
||||
|
||||
return &plat_iio->iio_devices[device];
|
||||
}
|
||||
|
||||
@@ -271,6 +274,191 @@ mraa_iio_trigger_buffer(mraa_iio_context dev, void (*fptr)(char* data), void* ar
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_iio_get_event_data(mraa_iio_context dev)
|
||||
{
|
||||
const struct dirent *ent;
|
||||
DIR* dir;
|
||||
int event_num = 0;
|
||||
char buf[MAX_SIZE];
|
||||
char readbuf[32];
|
||||
int fd;
|
||||
int ret = 0;
|
||||
int padint = 0;
|
||||
int curr_bytes = 0;
|
||||
char shortbuf, signchar;
|
||||
memset(buf, 0, MAX_SIZE);
|
||||
snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS, dev->num);
|
||||
dir = opendir(buf);
|
||||
if (dir != NULL) {
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
|
||||
event_num++;
|
||||
}
|
||||
}
|
||||
dev->event_num = event_num;
|
||||
mraa_iio_event* event;
|
||||
dev->events = calloc(event_num, sizeof(mraa_iio_event));
|
||||
if ( dev->events == NULL)
|
||||
{
|
||||
closedir(dir);
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
}
|
||||
rewinddir(dir);
|
||||
event_num = 0;
|
||||
while ((ent = readdir(dir)) != NULL)
|
||||
{
|
||||
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
|
||||
event = &dev->events[event_num];
|
||||
event->name = strdup(ent->d_name);
|
||||
snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS "/%s", dev->num, ent->d_name);
|
||||
fd = open(buf, O_RDONLY);
|
||||
if (fd > 0) {
|
||||
if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
event->enabled = ((int) strtol(readbuf, NULL, 10));
|
||||
//Todo, read other event info.
|
||||
event_num++;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_iio_event_read(mraa_iio_context dev, const char* attribute, float* data)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, 64, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS "/%s", dev->num, attribute);
|
||||
int fd = open(buf, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
int len = read(fd, &buf, 64);
|
||||
*data = strtol(buf, NULL, 10);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_iio_event_write(mraa_iio_context dev, const char* attribute, const char* data)
|
||||
{
|
||||
int len;
|
||||
char buf[128];
|
||||
snprintf(buf, 128, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS "/%s", dev->num, attribute);
|
||||
int fd = open(buf, O_WRONLY);
|
||||
if (fd != -1) {
|
||||
int len = write(fd, data, ( strlen(data) +1 ));
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_iio_event_poll_nonblock(int fd, struct iio_event_data* data)
|
||||
{
|
||||
struct pollfd pfd;
|
||||
|
||||
if (fd < 0) {
|
||||
return MRAA_ERROR_INVALID_RESOURCE;
|
||||
}
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
// Wait for it forever or until pthread_cancel
|
||||
// poll is a cancelable point like sleep()
|
||||
int x = poll(&pfd, 1, -1);
|
||||
|
||||
read(fd, data, sizeof(struct iio_event_data));
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_iio_event_poll(mraa_iio_context dev, struct iio_event_data* data)
|
||||
{
|
||||
char bu[MAX_SIZE];
|
||||
int ret;
|
||||
int event_fd;
|
||||
int fd;
|
||||
|
||||
sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
|
||||
fd = open(bu, 0);
|
||||
ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
|
||||
close(fd);
|
||||
|
||||
if (ret == -1 || event_fd == -1)
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
|
||||
ret = read(event_fd, data, sizeof(struct iio_event_data));
|
||||
|
||||
close(event_fd);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static void*
|
||||
mraa_iio_event_handler(void* arg)
|
||||
{
|
||||
struct iio_event_data data;
|
||||
mraa_iio_context dev = (mraa_iio_context) arg;
|
||||
|
||||
for (;;) {
|
||||
if (mraa_iio_event_poll_nonblock(dev->fp_event, &data) == MRAA_SUCCESS) {
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
dev->isr_event(&data);
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||
} else {
|
||||
// we must have got an error code so die nicely
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data), void* args)
|
||||
{
|
||||
int ret;
|
||||
char bu[MAX_SIZE];
|
||||
if (dev->thread_id != 0) {
|
||||
return MRAA_ERROR_NO_RESOURCES;
|
||||
}
|
||||
|
||||
sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
|
||||
dev->fp = open(bu, O_RDONLY | O_NONBLOCK);
|
||||
if (dev->fp == -1) {
|
||||
return MRAA_ERROR_INVALID_RESOURCE;
|
||||
}
|
||||
ret = ioctl(dev->fp, IIO_GET_EVENT_FD_IOCTL, &dev->fp_event);
|
||||
close(dev->fp);
|
||||
|
||||
if (ret == -1 || dev->fp_event == -1)
|
||||
{
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
dev->isr_event = fptr;
|
||||
pthread_create(&dev->thread_id, NULL, mraa_iio_event_handler, (void*) dev);
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_iio_event_extract_event(struct iio_event_data* event, int* chan_type, int* modifier, int* type, int* direction, int* channel, int* channel2, int* different)
|
||||
{
|
||||
*chan_type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
|
||||
*modifier= IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
|
||||
*type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
|
||||
*direction = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
|
||||
*channel = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
|
||||
*channel2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
|
||||
*different = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
#if 0
|
||||
// does stop make any sense on iio devices?
|
||||
mraa_result_t
|
||||
|
||||
Reference in New Issue
Block a user