zoukankan      html  css  js  c++  java
  • 【Linux高级驱动】input子系统框架

    【1.input子系统框架(driversinput)】

    如何得出某个驱动所遵循的框架?
        1) 通过网络搜索
        2) 自己想办法跟内核代码!
             2.1 定位此驱动是属于哪种类型的(触摸屏驱动为字符设备)
             2.2 搜索register_chrdev得到,input.c
             2.3 分析input.c文件

    /*入口函数*/
     subsys_initcall(input_init); 
     input_init
      /*1.创建一个设备类*/
      class_register(&input_class);
      /*2.申请主设备号,注册操作方法,注册字符设备*/
      register_chrdev(13, "input", &input_fops);
      
      static const struct file_operations input_fops = {
       .owner = THIS_MODULE,
       .open  = input_open_file,
      };

           

            2.4 分析如何来用input子系统

       app:  open("/dev/xxx",...)
       =============================
       vfs:  sys_open
        ...
        ...
       input.c struct file_operations input_fops
         .open = input_open_file,
          
          /*1.根据次设备号,从input_table数组中,取出一个input_handler结构体*/
          handler = input_table[iminor(inode) >> 5];   //2
          /*2.取出input_handler里面的操作方法*/
          if (handler)
           new_fops = fops_get(handler->fops);      //evdev_fops
          old_fops = file->f_op;
          file->f_op = new_fops;       //file中的f_op覆盖了
          /*3.执行底层的open函数*/
          new_fops->open(inode, file);   //事件处理层的操作方法里面的open函数evdev_open
          evdev_open

           
          
            2.5 根据handler = input_table[iminor(inode) >> 5];
                猜测,有某段代码将input_handler放入了input_table[iminor(inode) >> 5]
                搜索input_table,看在哪里放了

       module_init(evdev_init);
       evdev_init    //driver/input/evdev.c
        /*注册一个handler*/
        input_register_handler(struct input_handler *handler)
         
         /*将input_handler放入input_table数组中*/
         input_table[handler->minor >> 5] = handler;
       static struct input_handler evdev_handler = {
        .event   = evdev_event,
        .connect  = evdev_connect,
        .disconnect  = evdev_disconnect,
        .fops   = &evdev_fops,
        .minor   = EVDEV_MINOR_BASE,
        .name   = "evdev",
        .id_table   = evdev_ids,
       };

    【input子系统框架讲解】

    1.input子系统的核心层(input.c)
        功能:1)给用户提供接口(register_chrdev,cdev,file_operations结构体)
             2)给用input子系统内部组件提供接口,建立三者之间的联系

    /*入口函数*/
    subsys_initcall(input_init); 
    input_init
     /*1.创建一个设备类*/
     class_register(&input_class);
     /*2.申请主设备号,注册操作方法,注册字符设备*/
     register_chrdev(13, "input", &input_fops);
     
     static const struct file_operations input_fops = {
      .owner = THIS_MODULE,
      .open = input_open_file,
     };


    2.input子系统的事件处理层(evdev.c)
        功能:专门用来为设备驱动层上报事件的

    /*入口函数*/
    module_init(evdev_init);
    evdev_init    //driver/input/evdev.c
     /*注册一个handler*/
     input_register_handler(struct input_handler *handler)
      
      /*将input_handler放入input_table数组中*/
      input_table[handler->minor >> 5] = handler;   //64/32 =2
    static struct input_handler evdev_handler = {  //表示事件处理句柄
     .event   = evdev_event,     //上报事件的时候,会调用此函数
     .connect  = evdev_connect,    //建立连接的时候,会调用此函数
     .disconnect  = evdev_disconnect,
     .fops   = &evdev_fops,     //事件处理方法(xxx_read)
     .minor   = EVDEV_MINOR_BASE,    //64
     .name   = "evdev",
     .id_table  = evdev_ids,
    };
    static const struct file_operations evdev_fops = {
     .owner   = THIS_MODULE,
     .read   = evdev_read,      //当应用程序来读数据的时候,便会调用此函数
     .write   = evdev_write,
     .poll   = evdev_poll,
     .open   = evdev_open,
     .release  = evdev_release,
     .unlocked_ioctl = evdev_ioctl,
     .fasync   = evdev_fasync,
     .flush   = evdev_flush
    };

    3.input子系统的设备驱动层(s3c2410_ts.c为例子)(是驱动工作人员的主要任务)
        功能:1)跟硬件交互,操作硬件,获取硬件的外部事件
             2)提交事件给事件处理层

    /*入口函数*/
    module_init(s3c2410ts_init);
     s3c2410ts_init
      /*注册一个平台驱动*/
      platform_driver_register(&s3c_ts_driver);
    static struct platform_driver s3c_ts_driver = {
     .driver         = {
      .name   = "samsung-ts",
      .owner  = THIS_MODULE,
    #ifdef CONFIG_PM
      .pm = &s3c_ts_pmops,
    #endif
     },
     .id_table = s3cts_driver_ids,
     .probe  = s3c2410ts_probe,
     .remove  = __devexit_p(s3c2410ts_remove),
    };
    /*匹配成功,则调用平台驱动中的probe函数*/
    s3c2410ts_probe
     /*猜测*/
     /*1.获取资源*/
     /*1.1 获取平台数据*/
     info = pdev->dev.platform_data;
     /*1.2 使能时钟*/
     ts.clock = clk_get(dev, "adc");
     clk_enable(ts.clock);
     /*1.3 获取中断资源*/
     ts.irq_tc = ret = platform_get_irq(pdev, 0);
     /*1.4 获取IO内存资源*/
     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     /*1.5 映射*/
     ts.io = ioremap(res->start, resource_size(res));
     /*1.6 注册中断*/
     ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,
         "s3c2410_ts_pen", ts.input);
     /*2. 申请ADC服务*/
     /*3. 初始化硬件(初始化触摸屏控制器)*/
     /*4. 构建一个struct input_dev结构体*/
     struct input_dev *input_dev;                //表示一个输入设备
     /*4.1 设置input_dev*/
     /*4.2 注册input_dev,注册到子系统(input子系统中)*/
     input_register_device(ts.input);


     

    【input子系统里面涉及的几个重要结构体】

    struct input_dev     //用来表示一个输入设备
    {
     unsigned long evbit[BITS_TO_LONGS(EV_CNT)];   //事件类型
     unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];  //按键类当中什么按键
     unsigned long relbit[BITS_TO_LONGS(REL_CNT)];  //相对位移的什么事件
     unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];  //绝对位移的什么事件
     ...
    };

    struct input_handler   //用来表示一个事件处理句柄
    {
     /*上报事件*/
     void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
     /*建立连接的*/
     int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
     const struct file_operations *fops;
     ...
    }

    struct input_handle    //用来建立input_dev与input_handler的连接的
    {
     ...
     struct input_dev *dev;
     struct input_handler *handler;
     struct list_head d_node;
     struct list_head h_node;
    }

    struct input_event    //用来表示一个输入事件
    {
     struct timeval time;  //事件产生的时间
     __u16 type;     //事件类型 EV_KEY
     __u16 code;     //事件码   KEY_A KEY_B
     __s32 value;    //事件值   1-按下 0-松开
    }

    【input子系统中涉及的重要函数:(input.c)】


     

    /*注册一个事件处理句柄*/
    int input_register_handler(struct input_handler *handler)
    void input_unregister_handler(struct input_handler *handler)
    /*注册一个输入设备*/
    int input_register_device(struct input_dev *dev)
    void input_unregister_device(struct input_dev *dev)
    /*提交事件到事件处理层*/
    void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
    /*提交按键类事件*/
    void input_report_key(struct input_dev *dev, unsigned int code, int value)
    /*提交相对位移事件*/
    void input_report_rel(struct input_dev *dev, unsigned int code, int value)
    /*提交绝对位移事件*/
    void input_report_abs(struct input_dev *dev, unsigned int code, int value)
    /*提交同步类事件,每上报完一次事件后,都必须要上报一个同步事件*/
    void input_sync(struct input_dev *dev)
    /*分配一个input_dev结构体*/
    struct input_dev *input_allocate_device(void)
    /*设置input_dev,设置它能产生哪类事件,设置它能产生哪些*/
    方法一:BIT_MASK(事件类型)  事件类型都在:linux/input.h
    例如:
    ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
    方法二:set_bit
    例如:
    set_bit(EV_KEY,ts.input->evbit);
    set_bit(EV_ABS,ts.input->evbit);
    set_bit(BIN_TOUCH,ts.input->keybit);

    【input子系统框架】

    【input子系统框架完整版】

    @成鹏致远

    (email:wwwlllll@126.com)

    (qq:552158509

     





  • 相关阅读:
    堆栈学习
    需要阅读的书籍
    Rust Book Lang Ch.19 Fully Qualified Syntax, Supertraits, Newtype Pattern, type aliases, never type, dynamic sized type
    Rust Lang Book Ch.19 Placeholder type, Default generic type parameter, operator overloading
    Rust Lang Book Ch.19 Unsafe
    Rust Lang Book Ch.18 Patterns and Matching
    Rust Lang Book Ch.17 OOP
    Rust Lang Book Ch.16 Concurrency
    Rust Lang Book Ch.15 Smart Pointers
    HDU3966-Aragorn's Story-树链剖分-点权
  • 原文地址:https://www.cnblogs.com/lcw/p/3802617.html
Copyright © 2011-2022 走看看