虚拟鼠标TP设备驱动

#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");

猜你喜欢

转载自blog.csdn.net/touxiong/article/details/34413059
今日推荐