rendered paste body#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/pci.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
struct input_dev *aev_abs_dev;
static struct platform_device *aev_dev;
/*
* c: 0 = abs, 1 = key
* x/y: ABS_X/ABS_Y coordinates
* b: BTN_TOUCH, 0 = release, 1 = touch, same for pressure
*/
static ssize_t write_abs(struct device *dev, struct device_attribute *attr, const char *buffer, size_t count)
{
int c, x, y, b;
sscanf(buffer, "%d %d %d %d", &c, &x, &y, &b);
printk("%d %d %d %d\n", c, x, y, b);
if(c == 0)
{
input_report_abs(aev_abs_dev, ABS_MT_TOUCH_MAJOR, 1);
input_report_abs(aev_abs_dev, ABS_MT_WIDTH_MAJOR, 1);
input_report_abs(aev_abs_dev, ABS_MT_POSITION_X, x);
input_report_abs(aev_abs_dev, ABS_MT_POSITION_Y, y);
input_mt_sync(aev_abs_dev);
}
else if(c == 1)
{
input_report_abs(aev_abs_dev, ABS_MT_TOUCH_MAJOR, b);
input_report_abs(aev_abs_dev, ABS_MT_WIDTH_MAJOR, b);
input_report_abs(aev_abs_dev, ABS_MT_POSITION_X, x);
input_report_abs(aev_abs_dev, ABS_MT_POSITION_Y, y);
input_report_key(aev_abs_dev, BTN_TOUCH, b);
input_mt_sync(aev_abs_dev);
}
/* This command does not function and will be removed... */
else if(c == 2)
{
//input_set_abs_params(aev_abs_dev, ABS_X, 0, x, 0, 0);
//input_set_abs_params(aev_abs_dev, ABS_Y, 0, y, 0, 0);
}
else if(c == 3)
{
// raw command (used to send events as they come)
int ev = x;
int code = y;
int val = b;
input_event(aev_abs_dev, ev, code, val);
// no sync command for raw command. return immediately.
return (count);
}
else if(c > 3)
{
/*
* KEY_ESC happens to be 1. This is what I get for trying to squeeze
* this into the original keyless design without adapting it properly.
*/
input_report_key(aev_abs_dev, c - 3, b);
}
input_sync(aev_abs_dev);
return(count);
}
DEVICE_ATTR(abs, 0666, NULL, write_abs);
static struct attribute *abs_attrs[] =
{
&dev_attr_abs.attr,
NULL
};
static struct attribute_group abs_attr_group =
{
.attrs = abs_attrs,
};
int __init aev_init(void)
{
aev_dev = platform_device_register_simple("aev", -1, NULL, 0);
if(IS_ERR(aev_dev))
{
printk ("aev_init: error\n");
return(PTR_ERR(aev_dev));
}
sysfs_create_group(&aev_dev->dev.kobj, &abs_attr_group);
aev_abs_dev = input_allocate_device();
if(!aev_abs_dev)
{
printk("Bad input_allocate_device()\n");
return -ENOMEM;
}
aev_abs_dev->name = "aev_abs";
aev_abs_dev->phys = "aev_abs/input0";
aev_abs_dev->id.bustype = BUS_VIRTUAL;
aev_abs_dev->id.version = 0x0100;
set_bit(EV_KEY, aev_abs_dev->evbit);
set_bit(EV_ABS, aev_abs_dev->evbit);
/*
* Rather than specify the size of the screen, AEV uses
* a max x and y of 2000. This requires AIW to scale
* the coordinates appropriately, but allows the code
* to function with any display resolution.
*/
/*
input_set_abs_params(aev_abs_dev, ABS_X, 0, 2000, 0, 0);
input_set_abs_params(aev_abs_dev, ABS_Y, 0, 2000, 0, 0);
set_bit(ABS_X, aev_abs_dev->absbit);
set_bit(ABS_Y, aev_abs_dev->absbit);
*/
/* expose multi-touch capabilities */
input_set_abs_params(aev_abs_dev, ABS_MT_POSITION_X, 0, 2000, 0, 0);
input_set_abs_params(aev_abs_dev, ABS_MT_POSITION_Y, 0, 2000, 0, 0);
input_set_abs_params(aev_abs_dev, ABS_MT_TOUCH_MAJOR, 0, 8, 0, 0);
input_set_abs_params(aev_abs_dev, ABS_MT_WIDTH_MAJOR, 0, 8, 0, 0);
set_bit(ABS_MT_POSITION_X, aev_abs_dev->absbit);
set_bit(ABS_MT_POSITION_Y, aev_abs_dev->absbit);
set_bit(ABS_MT_TOUCH_MAJOR, aev_abs_dev->absbit);
set_bit(ABS_MT_WIDTH_MAJOR, aev_abs_dev->absbit);
set_bit(BTN_TOUCH, aev_abs_dev->keybit);
set_bit(KEY_ESC, aev_abs_dev->keybit);
set_bit(KEY_HOME, aev_abs_dev->keybit);
set_bit(KEY_RIGHTMETA, aev_abs_dev->keybit);
set_bit(KEY_UP, aev_abs_dev->keybit);
set_bit(KEY_DOWN, aev_abs_dev->keybit);
set_bit(KEY_SEARCH, aev_abs_dev->keybit);
set_bit(KEY_RIGHT, aev_abs_dev->keybit);
set_bit(KEY_LEFT, aev_abs_dev->keybit);
input_register_device(aev_abs_dev);
printk("AEV initialized\n");
return(0);
}
void aev_cleanup(void)
{
input_unregister_device(aev_abs_dev);
sysfs_remove_group(&aev_dev->dev.kobj, &abs_attr_group);
platform_device_unregister(aev_dev);
}
module_init(aev_init);
module_exit(aev_cleanup);
MODULE_LICENSE("GPL");