#include <linux/module.h> // For module specific items
#include <linux/moduleparam.h> // For new moduleparam's
#include <linux/types.h> // For standard types (like size_t)
#include <linux/errno.h> // For the -ENODEV/... values
#include <linux/kernel.h> // For dbmsg/panic/...
#include <linux/fs.h> // For file operations
#include <linux/ioport.h> // For io-port access
#include <linux/platform_device.h> // For platform_driver framework
#include <linux/init.h> // For __init/__exit/...
#include <linux/uaccess.h> // For copy_to_user/put_user/...
#include <linux/io.h> // For inb/outb/...
#include <linux/gpio.h> // GPIO
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h> //kamlloc
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/kmod.h>
#include <linux/mm.h>
#include <asm/system.h>
#include <linux/hrtimer.h>
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <mach/mt_pwm.h>
#include <mach/mt_typedefs.h>
//#include <mach/mt_clock_manager.h>
#include <mach/mt_reg_base.h>
#include <mach/mt_boot.h>
#include <mtk_kpd.h> /* custom file */
#include <mach/mt_gpio.h>
#include <linux/kthread.h>
#include <cust_alsps.h>
#define CURSOR_SET_DATA 0x5810
#define CURSOR_GET_DATA 0x5811
//#include <mach/irqs.h>
//#include <mach/eint.h>
//#include <mach/mt_gpio.h>
/**************gpio_config_start*********************/
//#include <linux/gpio.h>
#define BUFFERSIZE 1024
struct estar_gesture_t
{
struct cdev cdev;
struct class * estar_class;
dev_t devno;
int device_major;
int flag_cam3d; //CAMERA_3D or CAMERA_2D
unsigned char mem[BUFFERSIZE];
};
struct estar_gesture_t *estar_gesturep; /* 设备结构体指针*/
struct input_dev *pixart_input_dev = 0;
static struct task_struct *thread = NULL;
struct cursors
{
s32 x1,y1;
s32 x2,y2;
s32 x3,y3;
s32 x4,y4;
};
typedef struct cursors CURSOR;
static CURSOR coord;
CURSOR test[1000]={{1,2},{10,20},{10,20},{10,20}},*cursor_p;
static int cursor_halt = 0;/*updata flag*/
//static int cursor_flag = 0;/*interrupt flag*/
#define DEBUG 1
#if DEBUG
#define dbmsg(fmt, args ...) printk(KERN_NOTICE "gesture: %s[%d]: "fmt"\n", __FUNCTION__, __LINE__,##args)
#else
#define dbmsg(fmt, args ...)
#endif
//static int gesture_major = 252; // gesture_major = 0;
static int gesture_major = 0;
static int cursor_event_handler(void *unused);
static void cursor_down(s32 x, s32 y)
{
/* Report relative coordinates via the event interface */
#if 1
input_report_abs(pixart_input_dev, ABS_MT_PRESSURE, 100);
input_report_abs(pixart_input_dev, ABS_MT_TOUCH_MAJOR, 100);
input_report_key(pixart_input_dev, BTN_TOUCH, 1);
input_report_abs(pixart_input_dev, ABS_MT_POSITION_X, x);
input_report_abs(pixart_input_dev, ABS_MT_POSITION_Y, y);
input_mt_sync(pixart_input_dev);
input_sync(pixart_input_dev);
#else
input_report_key(pixart_input_dev, BTN_LEFT, 1);
input_report_rel(pixart_input_dev, REL_X, x);
input_report_rel(pixart_input_dev, REL_Y, y);
input_sync(pixart_input_dev);
#endif
}
static void cursor_up(s32 x, s32 y, s32 id)
{
//input_report_key(pixart_input_dev, BTN_TOUCH, 0);
//input_mt_sync(pixart_input_dev);
}
/*Coordination mapping*/
static void cursor_calibrate_driver(CURSOR *cursor_p)
{
if(cursor_p->x1 > 1080)cursor_p->x1 = 500;
if(cursor_p->y1 > 1920)cursor_p->x1 = 900;
}
static int cursor_event_handler(void *unused)
{
int cnt = 1000;
int x = 0,y = 0;
struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };/*优先级*/
sched_setscheduler(current, SCHED_RR, ¶m);
cursor_p = test;
do
{
set_current_state(TASK_INTERRUPTIBLE);
cursor_p = &test[cnt];
if(--cnt == 0)cnt =1000;
cursor_calibrate_driver(cursor_p);
//if (cursor_halt)
{
cursor_halt = 0;
//wait_event_interruptible(waiter, cursor_flag != 0);
//cursor_flag = 0;
//set_current_state(TASK_RUNNING);
dbmsg("x1 = %d,y1= %d",x,y);
//dbmsg("x2 = %d,y2= %d",coord.x2,coord.y2);
//dbmsg("x3 = %d,y3= %d",coord.x3,coord.y3);
//dbmsg("x4 = %d,y4= %d",coord.x4,coord.y4);
if(++x > 1080) x = 0;
if(++y > 1920) y = 0;
cursor_down(x,y);
msleep(20);
cursor_up(0,0,0);
msleep(30);
}
}
while(!kthread_should_stop());
return 0;
}
static long gesture_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
// cmd = (unsigned int)file; //解决与2.3版本兼容问题
dbmsg("cmd=0x%x, arg=0x%x", cmd, (unsigned int)arg);
switch ( cmd ) {
case CURSOR_SET_DATA:
ret = copy_from_user(&coord, (int *)arg, sizeof(coord));
cursor_halt = 1;
dbmsg("ret=0x%x",ret);
break;
case CURSOR_GET_DATA:
ret = copy_to_user((int *)arg, &coord, sizeof(coord));
//memset(&coord,0,sizeof(coord));
dbmsg("ret=0x%x",ret);
break;
default:
{
break;
}
}
return 0;
}
int gesture_open (struct inode *inode, struct file *filp)
{
dbmsg("cam3d_open_flag: open");
return 0;
}
ssize_t gesture_read(struct file *filp, char __user *buff, size_t count, loff_t *ppos)
{
int ret = 0;
struct estar_gesture_t *dev = filp->private_data; /*通过文件私有数据指针得到设备结构体,和前面的open对应*/
if ( count > BUFFERSIZE )
count = BUFFERSIZE;
/*内核空间->用户空间*/
if ( copy_to_user(buff, (void *)(dev->mem), count) )
{
ret = -EFAULT;
}
memset(dev->mem, 0, BUFFERSIZE);
return count;
}
ssize_t gesture_write(struct file *filp, const char __user *buff, size_t count, loff_t *ppos)
{
int ret = 0;
struct estar_gesture_t *dev = filp->private_data; /*通过文件私有数据指针得到设备结构体,和前面?膐pen对应*/
if (count > BUFFERSIZE)
count = BUFFERSIZE;
//dbmsg("write: copy_from_user: buf=%s", buff);
if ( copy_from_user( dev->mem , buff, count))
{
ret = -EFAULT;
return ret;
}
return count;
}
static int gesture_release(struct inode *node, struct file *file)
{
return 0;
}
static struct file_operations gesture_remap_ops = {
.owner = THIS_MODULE,
.open = gesture_open,
.release = gesture_release,
.read = gesture_read,
.write = gesture_write,
.unlocked_ioctl = gesture_ioctl, //ioctl
};
static void gesture_setup_cdev(struct cdev *dev, int minor,
struct file_operations *fops)
{
int err;
cdev_init(dev, fops);
dev->owner = THIS_MODULE;
dev->ops = fops;
err = cdev_add (dev, estar_gesturep->devno, 1);
if (err)
dbmsg (KERN_NOTICE "Error %d adding gesture %d", err, minor);
}
static int __init gesture_init(void)
{
int result,err;
dbmsg("gesture init");
estar_gesturep = kmalloc(sizeof(struct estar_gesture_t), GFP_KERNEL);
if(NULL == estar_gesturep)
{
dbmsg("NO Memory!");
return -1;
}
memset(estar_gesturep, 0, sizeof(struct estar_gesture_t));
estar_gesturep->devno = MKDEV(gesture_major, 0);
result = alloc_chrdev_region(&estar_gesturep->devno, 0, 1, "gesture");
estar_gesturep->device_major= MAJOR(estar_gesturep->devno);
if (result < 0) {
dbmsg(KERN_WARNING "gesture: unable to get major %d\n", estar_gesturep->device_major);
return result;
}
if (estar_gesturep->device_major== 0)
estar_gesturep->device_major= result;
gesture_setup_cdev(&estar_gesturep->cdev, 0, &gesture_remap_ops);
estar_gesturep->estar_class= class_create(THIS_MODULE, "gesture");
device_create(estar_gesturep->estar_class, NULL, estar_gesturep->devno, NULL, "gesture");
/* allocate input device */
pixart_input_dev = input_allocate_device();
if (!pixart_input_dev) {
dbmsg("Bad input_alloc_device()\n");
}
/* Announce that the virtual mouse will generate
relative coordinates */
#if 1
/*********** register input device **************/
set_bit(EV_ABS, pixart_input_dev->evbit);
set_bit(EV_KEY, pixart_input_dev->evbit);
set_bit(ABS_X, pixart_input_dev->absbit);
set_bit(ABS_Y, pixart_input_dev->absbit);
set_bit(ABS_PRESSURE, pixart_input_dev->absbit);
set_bit(BTN_TOUCH, pixart_input_dev->keybit);
set_bit(INPUT_PROP_DIRECT, pixart_input_dev->propbit);
set_bit(ABS_DISTANCE, pixart_input_dev->absbit);
set_bit(ABS_MT_TRACKING_ID, pixart_input_dev->absbit);
set_bit(ABS_MT_TOUCH_MAJOR, pixart_input_dev->absbit);
set_bit(ABS_MT_TOUCH_MINOR, pixart_input_dev->absbit);
set_bit(ABS_MT_POSITION_X, pixart_input_dev->absbit);
set_bit(ABS_MT_POSITION_Y, pixart_input_dev->absbit);
input_set_abs_params(pixart_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
input_set_abs_params(pixart_input_dev, ABS_MT_POSITION_X, 0, 1080, 0, 0);
input_set_abs_params(pixart_input_dev, ABS_MT_POSITION_Y, 0, 1920, 0, 0);
input_set_abs_params(pixart_input_dev, ABS_MT_TOUCH_MAJOR, 0, 100, 0, 0);
input_set_abs_params(pixart_input_dev, ABS_MT_TOUCH_MINOR, 0, 100, 0, 0);
input_set_abs_params(pixart_input_dev, ABS_X, 0, 1080, 0, 0);
input_set_abs_params(pixart_input_dev, ABS_Y, 0, 1920, 0, 0);
input_abs_set_res(pixart_input_dev, ABS_X, 1080);
input_abs_set_res(pixart_input_dev, ABS_Y, 1920);
input_set_abs_params(pixart_input_dev, ABS_PRESSURE, 0, 255, 0, 0);
#else
//Announce that the virtual mouse will generate
set_bit(BTN_LEFT, pixart_input_dev->keybit);
set_bit(EV_REL, pixart_input_dev->evbit);
set_bit(REL_X, pixart_input_dev->relbit);
set_bit(REL_Y, pixart_input_dev->relbit);
#endif
/* Register with the input subsystem */
result = input_register_device(pixart_input_dev);
if (result < 0) {
dbmsg( "Virtual Mouse Driver Initialized fail\n");
return result;
}
dbmsg("Virtual Mouse Driver Initialized.\n");
//cursor_event_handler();
thread = kthread_run(cursor_event_handler, 0, "GESTURE");
if (IS_ERR(thread))
{
err = PTR_ERR(thread);
dbmsg("GESTURE" " failed to create kernel thread: %d", err);
}
return 0;
}
static void __exit gesture_cleanup(void)
{
/* Unregister from the input subsystem */
input_unregister_device(pixart_input_dev);
device_destroy(estar_gesturep->estar_class,estar_gesturep->devno);
class_destroy(estar_gesturep->estar_class);
cdev_del(&estar_gesturep->cdev);
unregister_chrdev_region(estar_gesturep->devno, 1);
dbmsg("gesture device uninstalled\n");
}
module_init(gesture_init);
module_exit(gesture_cleanup);
MODULE_AUTHOR("www.estar.cn");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("1.0");
虚拟鼠标TP设备驱动
最新推荐文章于 2022-09-17 22:00:50 发布