鼠标驱动之-sys节点-input子系统

首先需要了解sys节点和linux驱动编程的知识,在linux内核<linux/>下有着对应的实现。本例实现创建sys节点,外围程序通过input子系统控制鼠标位置。

第一步编写驱动代码,创建sys节点:

    1. #include <linux/module.h>  
    2. #include <linux/platform_device.h>  
    3. #include <linux/slab.h>  
    4. #include <linux/input.h>  
    5. #include <linux/kthread.h>  
    6. #include <linux/semaphore.h>  
    7.   
    8. struct v_dev{  
    9.     struct platform_device *p_dev;    
    10.     struct input_dev *input;  
    11.     int x;  
    12.     int y;  
    13.     struct task_struct *run_thread;  
    14.     struct semaphore sem;  
    15. };  
    16.   
    17. struct v_dev *vmouse_dev = NULL;  
    18.   
    19. static ssize_t write_pos(struct device *dev, struct device_attribute *attr,  
    20.              const char *buf, size_t count)  
    21. {  
    22.     int x,y;  
    23.     sscanf(buf,"%d%d",&x,&y);  
    24.     vmouse_dev->x = x;  
    25.     vmouse_dev->y =y;  
    26.   
    27.     //post 信号量  
    28.     up(&vmouse_dev->sem);      
    29.   
    30.     return count;  
    31. }  
    32.   
    33. static ssize_t show_pos(struct device *dev, struct device_attribute *attr,  
    34.             char *buf){  
    35.     return sprintf(buf,"(%d,%d) ",vmouse_dev->x,vmouse_dev->y);  
    36. }  
    37.   
    38. DEVICE_ATTR(pos,0644,show_pos,write_pos);  
    39.   
    40. static int vmouse_thread(void *data)  
    41. {  
    42.     int x,y;  
    43.     struct v_dev *vmouse_dev = (struct v_dev*)data;  
    44.     struct semaphore *sema = &(vmouse_dev->sem);  
    45.       
    46.     printk(KERN_INFO "vmouse thread running ");  
    47.       
    48.     while(1){  
    49.         //等待信号量  
    50.         while((down_interruptible(sema)) == -EINTR){} ;  
    51.               
    52.         x = vmouse_dev->x;  
    53.         y = vmouse_dev->y;  
    54.         input_report_abs(vmouse_dev->input,ABS_X,x);  
    55.         input_report_abs(vmouse_dev->input,ABS_Y,y);  
    56.         input_sync(vmouse_dev->input);  
    57.   
    58.         printk("vmouse thread report ");  
    59.     }  
    60.   
    61.     return 0;  
    62. }     
    63.   
    64. static int vmouse_probe(struct platform_device *pdev)  
    65. {  
    66.     int ret = -1;  
    67.     printk("%s debug  ",__func__);  
    68.       
    69.     if(vmouse_dev->p_dev == pdev){  
    70.         printk("platform device is same ");  
    71.     }  
    72.       
    73.     vmouse_dev->input = input_allocate_device();  
    74.     if(!(vmouse_dev->input)){  
    75.         printk("%s request input deivce error ",__func__);  
    76.         goto alloc_input;  
    77.     }  
    78.       
    79.     vmouse_dev->input->name = "vmouse";  
    80.     set_bit(EV_ABS,vmouse_dev->input->evbit);  
    81.     input_set_abs_params(vmouse_dev->input, ABS_X, -1024, 1024, 0, 0);  
    82.     input_set_abs_params(vmouse_dev->input, ABS_Y, -1024, 1024, 0, 0);  
    83.   
    84.     ret = input_register_device(vmouse_dev->input);  
    85.     if(ret < 0){  
    86.         printk("%s register input device error ",__func__);  
    87.         goto input_register;  
    88.     }  
    89.       
    90.     device_create_file(&pdev->dev,&dev_attr_pos);  
    91. //初始化信号量,在线程中要用到  
    92.     sema_init(&(vmouse_dev->sem),0);   
    93.   
    94.     vmouse_dev->run_thread = kthread_run(vmouse_thread,vmouse_dev,"vmouse_thread");  
    95.       
    96.     return 0;  
    97.   
    98. input_register:  
    99.     input_free_device(vmouse_dev->input);  
    100. alloc_input:  
    101.     kfree(vmouse_dev);  
    102.     return ret;  
    103. }  
    104.   
    105. static struct platform_driver vmouse_driver = {  
    106.     .probe = vmouse_probe,  
    107.     .driver = {  
    108.         .owner = THIS_MODULE,  
    109.         .name = "v_mouse",  
    110.     },  
    111. };  
    112.   
    113. static int __init vmouse_init(void)  
    114. {  
    115.     int ret =-1;  
    116.       
    117.     printk("%s ", __func__);  
    118.       
    119.     vmouse_dev = kzalloc(sizeof(struct v_dev),GFP_KERNEL);  
    120.     if(vmouse_dev == NULL){  
    121.         printk("%s alloc memory  error ",__func__);  
    122.         return -ENOMEM;  
    123.     }  
    124.   
    125.     vmouse_dev->p_dev= platform_device_register_simple("v_mouse",-1,NULL,0);   
    126.     if(!(vmouse_dev->p_dev)){  
    127.         printk("%s register platform device error ",__func__);  
    128.         return ret;  
    129.     }  
    130.       
    131.     ret = platform_driver_register(&vmouse_driver);  
    132.     if(ret < 0){  
    133.         printk("%s register driver error ",__func__);  
    134.         return ret;  
    135.     }  
    136.   
    137.     return 0;  
    138. }  
    139.   
    140. static void __exit vmouse_exit(void)  
    141. {  
    142.     printk("%s ", __func__);  
    143.     if(vmouse_dev->input != NULL){  
    144.         input_unregister_device(vmouse_dev->input);  
    145.     }  
    146.     printk("%s debug__1 ",__func__);  
    147.       
    148.     if(vmouse_dev != NULL){  
    149.     platform_device_unregister(vmouse_dev->p_dev);  
    150.     }  
    151.     printk("%s debug__2 ",__func__);  
    152.       
    153.     platform_driver_unregister(&vmouse_driver);  
    154.     printk("%s debug__3 ",__func__);  
    155.       
    156.     kfree(vmouse_dev);  
    157.     printk("%s debug__4 ",__func__);  
    158. }  
    159.   
    160. module_init(vmouse_init);  
    161. module_exit(vmouse_exit);  
    162.   
    163. MODULE_LICENSE("GPL");  
    164. MODULE_AUTHOR("oracleloyal@gmail.com“); 
    165. 编写makefile:
    166.   1 ifeq ($(KERNELRELEASE),)
        2 #KERNEL_DIR:=/home/archermind/zhaoxi/bsw_ww02_2016/kernel/cht
        3 KERNEL_DIR:=/usr/src/linux-headers-3.13.0-32-generic
        4 PWD:=$(shell pwd)
        5 modules:
        6     $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
        7 modules_install:
        8     $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
        9 clean:
       10     rm -rf  .*.cmd *.ko  *.o modules.order  Module.symvers *mod.c
       11     .PHONY: modules modules_install clean
       12 else
       13     modules-objs := sys.o
       14     obj-m := sys.o
       15 endif
    167. 在当前makefile路径下执行make
    168. sudo insmod **.ko
    169. 加载驱动---会在/sys/devices/platform下出现节点,并且/dev/input下会出先对应的可读写的节点。
    170. 驱动的卸载sudo rmmod modules
    171. 编写测试程序:
      1. #include <fcntl.h>  
      2. #include <linux/input.h>  
      3. #include <stdio.h>  
      4. //要看自己的节点了  ---》特别注意去看自己多出的到底是哪个节点这里需要改动哦
      5. #define EVENT_DEV "/dev/input/event5"  
      6.   
      7. int main(void)  
      8. {  
      9.     struct input_event ev;  
      10.     int count,x,y;  
      11.   
      12.     int fd = open(EVENT_DEV, O_RDWR);  
      13.     if(fd < 0){  
      14.         printf("open %s failed ",EVENT_DEV);  
      15.         return 0;  
      16.     }  
      17.   
      18.     while(1){  
      19.         count = read(fd, &ev,sizeof(struct input_event));  
      20.         if(EV_ABS == ev.type){  
      21.             if(ev.code == ABS_X){  
      22.                 x = ev.value;  
      23.             }else if(ev.code == ABS_Y){  
      24.                 y = ev.value;  
      25.             }  
      26.             printf("position: x=%d, y=%d ",x,y);  
      27.         }else if(EV_SYN == ev.type){  
      28.                 puts("sync!");  
      29.         }  
      30.     }  
      31.   
      32.     return 0;     
      33. 先运行应用程序:./test_sys  
        在另一个终端执行:echo "90 90" >/sys/devices/platform/v_mouse/pos

        你就会看到你input设备上报的坐标,打印信息如下:

        position: x=90, y=0
        position: x=90, y=90
        sync!
      34. 完毕!
原文地址:https://www.cnblogs.com/oracleloyal/p/5358150.html