Blame kacpimon/input_layer.c

Packit Service 26469c
/*
Packit Service 26469c
 *  input_layer - Kernel ACPI Event Input Layer Interface
Packit Service 26469c
 *
Packit Service 26469c
 *  Handles the details of getting kernel ACPI events from the input
Packit Service 26469c
 *  layer (/dev/input/event*).
Packit Service 26469c
 *
Packit Service 26469c
 *  Inspired by (and in some cases blatantly lifted from) Vojtech Pavlik's
Packit Service 26469c
 *  evtest.c.
Packit Service 26469c
 *
Packit Service 26469c
 *  Copyright (C) 2008, Ted Felix (www.tedfelix.com)
Packit Service 26469c
 *
Packit Service 26469c
 *  This program is free software; you can redistribute it and/or modify
Packit Service 26469c
 *  it under the terms of the GNU General Public License as published by
Packit Service 26469c
 *  the Free Software Foundation; either version 2 of the License, or
Packit Service 26469c
 *  (at your option) any later version.
Packit Service 26469c
 *
Packit Service 26469c
 *  This program is distributed in the hope that it will be useful,
Packit Service 26469c
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 26469c
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 26469c
 *  GNU General Public License for more details.
Packit Service 26469c
 *
Packit Service 26469c
 *  You should have received a copy of the GNU General Public License
Packit Service 26469c
 *  along with this program; if not, write to the Free Software
Packit Service 26469c
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit Service 26469c
 *
Packit Service 26469c
 *  (tabs at 4)
Packit Service 26469c
 */
Packit Service 26469c
Packit Service 26469c
/* system */
Packit Service 26469c
#include <stdio.h>
Packit Service 26469c
#include <unistd.h>
Packit Service 26469c
#include <fcntl.h>
Packit Service 26469c
#include <linux/input.h>
Packit Service 26469c
#include <string.h>
Packit Service 26469c
#include <errno.h>
Packit Service 26469c
#include <malloc.h>
Packit Service 26469c
#include <glob.h>
Packit Service 26469c
Packit Service 26469c
/* local */
Packit Service 26469c
#include "connection_list.h"
Packit Service 26469c
#include "kacpimon.h"
Packit Service 26469c
Packit Service 26469c
#include "input_layer.h"
Packit Service 26469c
Packit Service 26469c
#define DIM(a)  (sizeof(a) / sizeof(a[0]))
Packit Service 26469c
Packit Service 26469c
#define INPUT_LAYER_FS "/dev/input/event*"
Packit Service 26469c
Packit Service 26469c
/*-----------------------------------------------------------------*/
Packit Service 26469c
/* called when an input layer event is received */
Packit Service 26469c
static void process_input(int fd)
Packit Service 26469c
{
Packit Service 26469c
	struct input_event event;
Packit Service 26469c
	ssize_t nbytes;
Packit Service 26469c
Packit Service 26469c
	nbytes = read(fd, &event, sizeof(event));
Packit Service 26469c
Packit Service 26469c
	if (nbytes == 0) {
Packit Service 26469c
		printf("Input layer connection closed.\n");
Packit Service 26469c
		return;
Packit Service 26469c
	}
Packit Service 26469c
	
Packit Service 26469c
	if (nbytes < 0) {
Packit Service 26469c
		/* if it's a signal, bail */
Packit Service 26469c
		if (errno == EINTR)
Packit Service 26469c
			return;
Packit Service 26469c
		
Packit Service 26469c
		printf("Input layer read error: %s (%d)\n",
Packit Service 26469c
			strerror(errno), errno);
Packit Service 26469c
		return;
Packit Service 26469c
	}
Packit Service 26469c
Packit Service 26469c
	/* ??? Is it possible for a partial message to come across? */
Packit Service 26469c
	/*   If so, we've got more code to write... */
Packit Service 26469c
	
Packit Service 26469c
	if (nbytes != sizeof(event)) {
Packit Service 26469c
		printf("Input Layer unexpected Length\n");
Packit Service 26469c
		printf("  Expected: %lu   Got: %zd\n",
Packit Service 26469c
			(unsigned long) sizeof(event), nbytes);
Packit Service 26469c
		return;
Packit Service 26469c
	}
Packit Service 26469c
Packit Service 26469c
	/* If the Escape key was pressed, set the exitflag to exit. */
Packit Service 26469c
	if (event.type == EV_KEY  &&
Packit Service 26469c
	    event.code == KEY_ESC  &&
Packit Service 26469c
	    event.value == 1) {
Packit Service 26469c
		printf("Escape key pressed\n");
Packit Service 26469c
		exitflag = 1;
Packit Service 26469c
	}
Packit Service 26469c
Packit Service 26469c
	if (event.type == EV_SYN)
Packit Service 26469c
		printf("Input Layer:  Sync\n");
Packit Service 26469c
	else
Packit Service 26469c
		/* format and display the event struct in decimal */
Packit Service 26469c
		printf("Input Layer:  "
Packit Service 26469c
			"Type: %hu  Code: %hu  Value: %d\n",
Packit Service 26469c
			event.type, event.code, event.value);
Packit Service 26469c
}
Packit Service 26469c
Packit Service 26469c
#define BITS_PER_LONG (sizeof(long) * 8)
Packit Service 26469c
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
Packit Service 26469c
#define OFF(x)  ((x)%BITS_PER_LONG)
Packit Service 26469c
#define LONG(x) ((x)/BITS_PER_LONG)
Packit Service 26469c
#define test_bit(bit, array)	((array[LONG(bit)] >> OFF(bit)) & 1)
Packit Service 26469c
Packit Service 26469c
/*-----------------------------------------------------------------*
Packit Service 26469c
 * open each of the appropriate /dev/input/event* files for input  */
Packit Service 26469c
void open_input(void)
Packit Service 26469c
{
Packit Service 26469c
	char *filename = NULL;
Packit Service 26469c
	glob_t globbuf;
Packit Service 26469c
	unsigned i;
Packit Service 26469c
	int fd;
Packit Service 26469c
	struct connection c;
Packit Service 26469c
	int had_some_success = 0;
Packit Service 26469c
	char evname[256];
Packit Service 26469c
Packit Service 26469c
	/* get all the matching event filenames */
Packit Service 26469c
	glob(INPUT_LAYER_FS, 0, NULL, &globbuf);
Packit Service 26469c
Packit Service 26469c
	/* for each event file */
Packit Service 26469c
	for (i = 0; i < globbuf.gl_pathc; ++i)
Packit Service 26469c
	{
Packit Service 26469c
		filename = globbuf.gl_pathv[i];
Packit Service 26469c
Packit Service 26469c
		fd = open(filename, O_RDONLY | O_NONBLOCK);
Packit Service 26469c
		if (fd >= 0) {
Packit Service 26469c
			/* get this event file's name */
Packit Service 26469c
			strcpy(evname, "Unknown");
Packit Service 26469c
			ioctl(fd, EVIOCGNAME(sizeof(evname)), evname);
Packit Service 26469c
Packit Service 26469c
			printf("%s (%s) opened successfully\n", filename, evname);
Packit Service 26469c
			had_some_success = 1;
Packit Service 26469c
Packit Service 26469c
			/* add a connection to the list */
Packit Service 26469c
			c.fd = fd;
Packit Service 26469c
			c.process = process_input;
Packit Service 26469c
			add_connection(&c);
Packit Service 26469c
		}
Packit Service 26469c
		else
Packit Service 26469c
		{
Packit Service 26469c
			if (had_some_success == 1)
Packit Service 26469c
				continue;
Packit Service 26469c
			int errno2 = errno;
Packit Service 26469c
			printf("open for %s failed: %s (%d)\n", 
Packit Service 26469c
				filename, strerror(errno2), errno2);
Packit Service 26469c
			if (errno2 == EACCES)
Packit Service 26469c
				printf("  (try running as root)\n");
Packit Service 26469c
			if (errno2 == ENOENT)
Packit Service 26469c
				printf("  (input layer driver may not be present)\n");
Packit Service 26469c
		}
Packit Service 26469c
	}
Packit Service 26469c
Packit Service 26469c
	globfree(&globbuf);
Packit Service 26469c
}
Packit Service 26469c