• 鼠标驱动之-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. 完毕!
  • 相关阅读:
    docker镜像管理基础
    docker的基础应用
    mysql基础
    策略模式
    简单工厂模式
    hystrix-go简介
    手把手带你使用 go-kit(option)
    手把手带你使用 go-kit(组件扩充,服务发现)
    手把手带你使用 go-kit(客户端直连)
    手把手带你使用 go-kit(基础篇)
  • 原文地址:https://www.cnblogs.com/oracleloyal/p/5358150.html
Copyright © 2020-2023  润新知