From: Lay, Kuan Loon Date: Fri, 16 Oct 2015 01:18:32 +0000 (+0800) Subject: iio: added event api X-Git-Tag: v0.9.0~48 X-Git-Url: http://review.tizen.org/git/?p=contrib%2Fmraa.git;a=commitdiff_plain;h=4c41d2c2df31aebc64b4bb5a3483663cf4794d1f iio: added event api Signed-off-by: Lay, Kuan Loon Signed-off-by: Brendan Le Foll --- diff --git a/api/mraa/iio.h b/api/mraa/iio.h old mode 100644 new mode 100755 index 286a00f..a800f96 --- a/api/mraa/iio.h +++ b/api/mraa/iio.h @@ -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 * diff --git a/api/mraa/iio_kernel_headers.h b/api/mraa/iio_kernel_headers.h new file mode 100755 index 0000000..5fbe81f --- /dev/null +++ b/api/mraa/iio_kernel_headers.h @@ -0,0 +1,136 @@ +/* + * Author: Lay, Kuan Loon + * 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 +//#include + +//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 + +/** + * 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) diff --git a/examples/iio_driver.c b/examples/iio_driver.c old mode 100644 new mode 100755 index e2ca3e3..810a001 --- a/examples/iio_driver.c +++ b/examples/iio_driver.c @@ -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; } diff --git a/include/mraa_internal_types.h b/include/mraa_internal_types.h old mode 100644 new mode 100755 index 3eb54f8..70d4197 --- a/include/mraa_internal_types.h +++ b/include/mraa_internal_types.h @@ -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; }; diff --git a/src/iio/iio.c b/src/iio/iio.c old mode 100644 new mode 100755 index 366c4ed..8297ff5 --- a/src/iio/iio.c +++ b/src/iio/iio.c @@ -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