mirror of
https://github.com/netfun2000/lcd4linux.git
synced 2026-02-27 09:44:34 +08:00
git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1062 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
303 lines
7.1 KiB
C
303 lines
7.1 KiB
C
/* $Id: event.c 1040 2009-09-23 04:14:17Z michael $
|
|
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/event.c $
|
|
*
|
|
* generic timer handling
|
|
*
|
|
* Copyright (C) 2009 Ed Martin <edman007@edman007.com>
|
|
* Copyright (C) 2004, 2009 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* exported functions:
|
|
*
|
|
* int event_add(void (*callback) (void *data), void *data, const int fd, const int read, const int write);
|
|
* Adds a file description to watch
|
|
*
|
|
* int event_del(const int fd);
|
|
* Remove an event
|
|
*
|
|
* int event_modify(const int fd, const int read, const int write, const int active);
|
|
* Modify an event
|
|
*
|
|
* int named_event_add(char *event, void (*callback) (void *data), void *data);
|
|
* Add an event identified by a string
|
|
*
|
|
* int named_event_del(char *event, void (*callback) (void *data), void *data);
|
|
* delete the event identified by this string/callback/data
|
|
*
|
|
* int named_event_trigger(char *event); //call all calbacks for this event
|
|
* call the callbacks of all events that have identified as this string
|
|
*
|
|
* int event_process(const struct timespec *delay);
|
|
* process the event list
|
|
*
|
|
* void event_exit();
|
|
* releases all events
|
|
*
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <poll.h>
|
|
|
|
#include "debug.h"
|
|
#include "cfg.h"
|
|
#include "event.h"
|
|
|
|
#ifdef WITH_DMALLOC
|
|
#include <dmalloc.h>
|
|
#endif
|
|
|
|
typedef struct {
|
|
void (*callback) (event_flags_t flags, void *data);
|
|
void *data;
|
|
int fd;
|
|
int read;
|
|
int write;
|
|
int active;
|
|
int fds_id;
|
|
} event_t;
|
|
|
|
|
|
//our set of FDs
|
|
static event_t *events = NULL;
|
|
static int event_count = 0;
|
|
static void free_events(void);
|
|
|
|
int event_add(void (*callback) (event_flags_t flags, void *data), void *data, const int fd, const int read,
|
|
const int write, const int active)
|
|
{
|
|
event_count++;
|
|
events = realloc(events, sizeof(event_t) * event_count);
|
|
|
|
int i = event_count - 1;
|
|
events[i].callback = callback;
|
|
events[i].data = data;
|
|
events[i].fd = fd;
|
|
events[i].read = read;
|
|
events[i].write = write;
|
|
events[i].active = active;
|
|
events[i].fds_id = -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int event_process(const struct timespec *timeout)
|
|
{
|
|
int i, j;
|
|
struct pollfd *fds = malloc(sizeof(struct pollfd) * event_count);
|
|
for (i = 0, j = 0; i < event_count; i++) {
|
|
events[i].fds_id = -1;
|
|
if (events[i].active) {
|
|
events[i].fds_id = j;
|
|
fds[j].events = 0;
|
|
fds[j].fd = events[i].fd;
|
|
if (events[i].read) {
|
|
fds[j].events |= POLLIN;
|
|
}
|
|
if (events[i].write) {
|
|
fds[j].events |= POLLOUT;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
#if (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4)
|
|
int ready = ppoll(fds, j, timeout, NULL);
|
|
#else
|
|
int ready = poll(fds, j, timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000);
|
|
#endif
|
|
|
|
if (ready > 0) {
|
|
//search the file descriptors, call all relavant callbacks
|
|
for (i = 0, j = 0; i < event_count; i++) {
|
|
if (events[i].fds_id != j) {
|
|
continue;
|
|
}
|
|
if (fds[j].revents) {
|
|
int flags = 0;
|
|
if (fds[j].revents & POLLIN) {
|
|
flags |= EVENT_READ;
|
|
}
|
|
if (fds[j].revents & POLLOUT) {
|
|
flags |= EVENT_WRITE;
|
|
}
|
|
if (fds[j].revents & POLLHUP) {
|
|
flags |= EVENT_HUP;
|
|
}
|
|
if (fds[j].revents & POLLERR) {
|
|
flags |= EVENT_ERR;
|
|
}
|
|
events[i].callback(flags, events[i].data);
|
|
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
free(fds);
|
|
return 0;
|
|
|
|
}
|
|
|
|
int event_del(const int fd)
|
|
{
|
|
int i;
|
|
for (i = 0; i < event_count; i++) {
|
|
if (events[i].fd == fd) {
|
|
events[i] = events[event_count - 1];
|
|
break;
|
|
}
|
|
}
|
|
event_count--;
|
|
events = realloc(events, sizeof(event_t) * event_count);
|
|
return 0;
|
|
}
|
|
|
|
int event_modify(const int fd, const int read, const int write, const int active)
|
|
{
|
|
int i;
|
|
for (i = 0; i < event_count; i++) {
|
|
if (events[i].fd == fd) {
|
|
events[i].read = read;
|
|
events[i].write = write;
|
|
events[i].active = active;
|
|
break;
|
|
}
|
|
}
|
|
event_count--;
|
|
events = realloc(events, sizeof(event_t) * event_count);
|
|
return 0;
|
|
}
|
|
|
|
static void free_events(void)
|
|
{
|
|
if (events != NULL) {
|
|
free(events);
|
|
}
|
|
event_count = 0;
|
|
events = NULL;
|
|
|
|
}
|
|
|
|
void event_exit(void)
|
|
{
|
|
free_events();
|
|
}
|
|
|
|
/*
|
|
* Named events are the user facing side of the event subsystem
|
|
*
|
|
*/
|
|
|
|
|
|
//we rely on "=" working for copying these structs (no pointers except the callers)
|
|
typedef struct {
|
|
void (*callback) (void *data);
|
|
void *data;
|
|
} event_callback_t;
|
|
|
|
typedef struct {
|
|
char *name;
|
|
event_callback_t *c;
|
|
int callback_count;
|
|
} named_event_list_t;
|
|
|
|
|
|
static named_event_list_t *ev_names = NULL;
|
|
static int ev_count = 0;
|
|
|
|
int named_event_add(char *event, void (*callback) (void *data), void *data)
|
|
{
|
|
if (event == NULL || strlen(event) == 0) {
|
|
return 1;
|
|
}
|
|
if (callback == NULL) {
|
|
return 2;
|
|
}
|
|
int i;
|
|
for (i = 0; i < ev_count; i++) {
|
|
if (0 == strcmp(event, ev_names[i].name)) {
|
|
break;
|
|
}
|
|
}
|
|
if (i >= ev_count) {
|
|
//create the entry
|
|
ev_count++;
|
|
ev_names = realloc(ev_names, sizeof(named_event_list_t) * ev_count);
|
|
ev_names[i].name = strdup(event);
|
|
ev_names[i].callback_count = 0;
|
|
ev_names[i].c = NULL;
|
|
}
|
|
int j = ev_names[i].callback_count;
|
|
ev_names[i].callback_count++;
|
|
ev_names[i].c = realloc(ev_names[i].c, sizeof(event_callback_t) * ev_names[i].callback_count);
|
|
|
|
ev_names[i].c[j].callback = callback;
|
|
ev_names[i].c[j].data = data;
|
|
return 0;
|
|
}
|
|
|
|
int named_event_del(char *event, void (*callback) (void *data), void *data)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < ev_count; i++) {
|
|
if (0 == strcmp(event, ev_names[i].name)) {
|
|
break;
|
|
}
|
|
}
|
|
if (i >= ev_count) {
|
|
return 1; //nothing removed
|
|
}
|
|
for (j = 0; j < ev_names[i].callback_count; j++) {
|
|
if (ev_names[i].c[j].callback == callback && ev_names[i].c[j].data == data) {
|
|
ev_names[i].callback_count--;
|
|
ev_names[i].c[j] = ev_names[i].c[ev_names[i].callback_count];
|
|
ev_names[i].c = realloc(ev_names[i].c, sizeof(event_callback_t) * ev_names[i].callback_count);
|
|
if (ev_names[i].callback_count == 0) {
|
|
//drop this event
|
|
free(ev_names[i].name);
|
|
ev_count--;
|
|
ev_names[i] = ev_names[ev_count];
|
|
ev_names = realloc(ev_names, sizeof(named_event_list_t) * ev_count);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
int named_event_trigger(char *event)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < ev_count; i++) {
|
|
if (0 == strcmp(event, ev_names[i].name)) {
|
|
for (j = 0; j < ev_names[i].callback_count; j++) {
|
|
ev_names[i].c[j].callback(ev_names[i].c[j].data);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|