平台:tiny210SOC:s5pv210内核:Linux 3.0.8字符驱动:按键中断驱动源码:
 /*****************************************************************************
 简    述:简单字符型驱动程序,手动静态分配设备号,手动创建设备节点
 ******************************************************************************/
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <linux/interrupt.h>

 #include <mach/map.h>
 #include <mach/gpio.h>
 #include <mach/regs-gpio.h>
 #include <plat/gpio-cfg.h>

 #include <linux/slab.h>

 #define DEVICE_NAME        "buttons"

 struct button_desc {
     int gpio;
     int number;
     char *name;
 };

 static struct button_desc buttons[] = {
     { S5PV210_GPH2(), , "KEY0" },
     { S5PV210_GPH2(), , "KEY1" },
     { S5PV210_GPH2(), , "KEY2" },
     { S5PV210_GPH2(), , "KEY3" },
     { S5PV210_GPH3(), , "KEY4" },
     { S5PV210_GPH3(), , "KEY5" },
     { S5PV210_GPH3(), , "KEY6" },
     { S5PV210_GPH3(), , "KEY7" },
 };
 #define OK            (0)
 #define ERROR         (-1)

 struct cdev *gDev;
 struct file_operations *gFile;
 dev_t  devNum;
 unsigned ;
 ;
 ;

 static irqreturn_t button_interrupt(int irq, void *dev_id)
 {
     struct button_desc *bdata = (struct button_desc *)dev_id;

     int down;
     unsigned tmp;

     tmp = gpio_get_value(bdata->gpio);

     /* active low */
     down = !tmp;
     printk("KEY %d: %08x\n", bdata->number, down);

     return IRQ_HANDLED;
 }

 int butsOpen(struct inode *p, struct file *f)
 {

         int irq;
     int i;
     ;
     printk(KERN_EMERG"butsOpen\r\n");
     ; i < ARRAY_SIZE(buttons); i++) {
         if (!buttons[i].gpio)
             continue;

         irq = gpio_to_irq(buttons[i].gpio);
         err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,
                 buttons[i].name, (void *)&buttons[i]);
         if (err)
             break;
     }

     if (err) {
         i--;
         ; i--) {
             if (!buttons[i].gpio)
                 continue;

             irq = gpio_to_irq(buttons[i].gpio);
             disable_irq(irq);
             free_irq(irq, (void *)&buttons[i]);
         }

         return -EBUSY;
     }
     ;
 }

 int charDrvInit(void)
 {

     devNum = MKDEV(reg_major, reg_minor);

     printk(KERN_EMERG"devNum is %d\r\n", devNum);
     if(OK == register_chrdev_region(devNum, subDevNum, DEVICE_NAME))
     {
         printk(KERN_EMERG"register_chrdev_region ok\r\n");
     }
     else
     {
         printk(KERN_EMERG"register_chrdev_region error\r\n");
         return ERROR;
     }
     /*if(OK == alloc_chrdev_region(&devNum, subDevNum, subDevNum,"test"))
     {
         printk(KERN_EMERG"register_chrdev_region ok\r\n");
     }
     else
     {
         printk(KERN_EMERG"register_chrdev_region error\r\n");
         return ERROR;
     }*/

     gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
     gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);

     gFile->open = butsOpen;
 //注册设备函数到file_operations结构体gFile

    //gDev->owner = THIS_MODULE;
     gFile->owner = THIS_MODULE;
     cdev_init(gDev, gFile);
 //在cdev结构体中添加指针指向file_operations结构体gFile
     cdev_add(gDev, devNum, );
 //建立设备号与cdev结构体联系
     printk(KERN_EMERG"button driver initial done...\r\n");
     ;
 }

 void __exit charDrvExit(void)
 {
     int i;

     cdev_del(gDev);
     unregister_chrdev_region(devNum, subDevNum);
     return;
 }
 module_init(charDrvInit);
 module_exit(charDrvExit);
 MODULE_LICENSE("GPL");

 int butsOpen(struct inode *p, struct file *f)
 {

         int irq;
     int i;
     ;
     printk(KERN_EMERG"butsOpen\r\n");
     ; i < ARRAY_SIZE(buttons); i++) {
         if (!buttons[i].gpio)
             continue;

         irq = gpio_to_irq(buttons[i].gpio);
         err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,
                 buttons[i].name, (void *)&buttons[i]);
         if (err)
             break;
     }

     if (err) {
         i--;
         ; i--) {
             if (!buttons[i].gpio)
                 continue;

             irq = gpio_to_irq(buttons[i].gpio);
             disable_irq(irq);
             free_irq(irq, (void *)&buttons[i]);
         }

         return -EBUSY;
     }
     ;
 }
 #define gpio_to_irq    __gpio_to_irq
 int __gpio_to_irq(unsigned gpio)
 {
     struct gpio_chip    *chip;
     chip = gpio_to_chip(gpio);
     return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
 }
 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
 {
     struct s3c_gpio_chip *s3c_chip = container_of(chip,
             struct s3c_gpio_chip, chip);

     return s3c_chip->irq_base + offset;
 }
 static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
 {
     return gpio_desc[gpio].chip;//此处的gpio_desc[gpio].chip实际完成赋值在gpio-s5pv210.c中的s5pv210_gpiolib_init(void)函数中实现
 }

gpio_desc[gpio].chip实际完成赋值在gpio-s5pv210.c中的s5pv210_gpiolib_init(void)函数中的实现:

 static __init int s5pv210_gpiolib_init(void)
 {
     struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
     int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
     ;
     ;

     ; i < nr_chips; i++, chip++) {
         if (chip->config == NULL) {
             chip->config = &gpio_cfg;
             chip->group = gpioint_group++;
         }
         if (chip->base == NULL)
             chip->base = S5PV210_BANK_BASE(i);
     }

     samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
     s5p_register_gpioint_bank(IRQ_GPIOINT, , S5P_GPIOINT_GROUP_MAXNR);

     ;
 }
 static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
     {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_A0_NR,
             .label    = "GPA0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_A1_NR,
             .label    = "GPA1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_B_NR,
             .label    = "GPB",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_C0_NR,
             .label    = "GPC0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_C1_NR,
             .label    = "GPC1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_D0_NR,
             .label    = "GPD0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_D1_NR,
             .label    = "GPD1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_E0_NR,
             .label    = "GPE0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_E1_NR,
             .label    = "GPE1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_F0_NR,
             .label    = "GPF0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_F1_NR,
             .label    = "GPF1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_F2_NR,
             .label    = "GPF2",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_F3_NR,
             .label    = "GPF3",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_G0_NR,
             .label    = "GPG0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_G1_NR,
             .label    = "GPG1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_G2_NR,
             .label    = "GPG2",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_G3_NR,
             .label    = "GPG3",
         },
     }, {
         .config    = &gpio_cfg_noint,
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_I_NR,
             .label    = "GPI",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_J0_NR,
             .label    = "GPJ0",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_J1_NR,
             .label    = "GPJ1",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_J2_NR,
             .label    = "GPJ2",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_J3_NR,
             .label    = "GPJ3",
         },
     }, {
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_J4_NR,
             .label    = "GPJ4",
         },
     }, {
         .config    = &gpio_cfg_noint,
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_MP01_NR,
             .label    = "MP01",
         },
     }, {
         .config    = &gpio_cfg_noint,
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_MP02_NR,
             .label    = "MP02",
         },
     }, {
         .config    = &gpio_cfg_noint,
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_MP03_NR,
             .label    = "MP03",
         },
     }, {
         .config    = &gpio_cfg_noint,
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_MP04_NR,
             .label    = "MP04",
         },
     }, {
         .config    = &gpio_cfg_noint,
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_MP05_NR,
             .label    = "MP05",
         },
     }, {
         .base    = (S5P_VA_GPIO + 0xC00),
         .config    = &gpio_cfg_noint,
         .irq_base = IRQ_EINT(),
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_H0_NR,
             .label    = "GPH0",
             .to_irq = samsung_gpiolib_to_irq,
         },
     }, {
         .base    = (S5P_VA_GPIO + 0xC20),
         .config    = &gpio_cfg_noint,
         .irq_base = IRQ_EINT(),
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_H1_NR,
             .label    = "GPH1",
             .to_irq = samsung_gpiolib_to_irq,
         },
     }, {
         .base    = (S5P_VA_GPIO + 0xC40),
         .config    = &gpio_cfg_noint,
         .irq_base = IRQ_EINT(),
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_H2_NR,
             .label    = "GPH2",
             .to_irq = samsung_gpiolib_to_irq,
         },
     }, {
         .base    = (S5P_VA_GPIO + 0xC60),
         .config    = &gpio_cfg_noint,
         .irq_base = IRQ_EINT(),
         .chip    = {
             .),
             .ngpio    = S5PV210_GPIO_H3_NR,
             .label    = "GPH3",
             .to_irq = samsung_gpiolib_to_irq,
         },
     },
 };

struct s3c_gpio_chip s5pv210_gpio_4bit[]

 void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
2                        int nr_chips)
 {
     ; nr_chips--, chip++) {
         samsung_gpiolib_add_4bit(chip);
         s3c_gpiolib_add(chip);
     }
 }
 __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
 {
     struct gpio_chip *gc = &chip->chip;//将struct s3c_gpio_chip结构体成员结构体chip赋值给struct gpio_chip结构体局部变量gc
     int ret;

     BUG_ON(!chip->base);
     BUG_ON(!gc->label);
     BUG_ON(!gc->ngpio);

     spin_lock_init(&chip->lock);

     if (!gc->direction_input)
         gc->direction_input = s3c_gpiolib_input;
     if (!gc->direction_output)
         gc->direction_output = s3c_gpiolib_output;
     if (!gc->set)
         gc->set = s3c_gpiolib_set;
     if (!gc->get)
         gc->get = s3c_gpiolib_get;

 #ifdef CONFIG_PM
     if (chip->pm != NULL) {
         if (!chip->pm->save || !chip->pm->resume)
             printk(KERN_ERR "gpio: %s has missing PM functions\n",
                    gc->label);
     } else
         printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
 #endif

     /* gpiochip_add() prints own failure message on error. */
     ret = gpiochip_add(gc);
     )
         s3c_gpiolib_track(chip);
 }
 int gpiochip_add(struct gpio_chip *chip)
 {
     unsigned long    flags;
     ;
     unsigned    id;
     int        base = chip->base;

     ))
             && ) {
         status = -EINVAL;
         goto fail;
     }

     spin_lock_irqsave(&gpio_lock, flags);

     ) {
         base = gpiochip_find_base(chip->ngpio);
         ) {
             status = base;
             goto unlock;
         }
         chip->base = base;
     }

     /* these GPIO numbers must not be managed by another gpio_chip */
     for (id = base; id < base + chip->ngpio; id++) {
         if (gpio_desc[id].chip != NULL) {
             status = -EBUSY;
             break;
         }
     }
     ) {
         for (id = base; id < base + chip->ngpio; id++) {
             gpio_desc[id].chip = chip;//在这里gpio_desc[id].chip和struct s3c_gpio_chip建立联系

             /* REVISIT:  most hardware initializes GPIOs as
              * inputs (often with pullups enabled) so power
              * usage is minimized.  Linux code should set the
              * gpio direction first thing; but until it does,
              * we may expose the wrong direction in sysfs.
              */
             gpio_desc[id].flags = !chip->direction_input
                 ? ( << FLAG_IS_OUT)
                 : ;
         }
     }

     of_gpiochip_add(chip);

 unlock:
     spin_unlock_irqrestore(&gpio_lock, flags);

     if (status)
         goto fail;

     status = gpiochip_export(chip);
     if (status)
         goto fail;

     ;
 fail:
     /* failures here can mean systems won't boot... */
     pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",
         chip->,
         chip->label ? : "generic");
     return status;
 }

Linux字符设备驱动--No.1的更多相关文章

  1. 深入理解Linux字符设备驱动

    文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...

  2. Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】

    本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...

  3. Smart210学习记录----beep linux字符设备驱动

    今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈...但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决 ...

  4. Linux字符设备驱动实现

    Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...

  5. Linux字符设备驱动基本结构

    1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...

  6. (57)Linux驱动开发之三Linux字符设备驱动

    1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...

  7. Linux字符设备驱动框架

    字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...

  8. Linux 字符设备驱动模型

    一.使用字符设备驱动程序 1. 编译/安装驱动 在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码.因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块 2. 创建设备文件 通 ...

  9. linux字符设备驱动学习笔记(一):简单的字符设备驱动

    最近在鼓捣lnux字符设备驱动,在网上搜集的各种关于linux设备驱动的代码和注释,要么是针对2.4的,要么是错误百出,根本就不能运行成功,真希望大家在发博客的时候能认真核对下代码的正确性,特别是要把 ...

  10. Linux字符设备驱动

    一.字符设备基础 字符设备 二.字符设备驱动与用户空间访问该设备的程序三者之间的关系 三.字符设备模型 1.Linux内核中,使用 struct cdev 来描述一个字符设备 动态申请(构造)cdev ...

随机推荐

  1. 字符串模式匹配之KMP算法的next数组详解与C++实现

    相信来看next数组如何求解的童鞋已经对KMP算法是怎么回事有了一定的了解,这里就不再赘述,附上一个链接吧:https://www.cnblogs.com/c-cloud/p/3224788.html ...

  2. dbms_stats应用相关

    Q:     DBMS_STATS.GATHER_SCHEMA_STATS ('schema_name');        使用这个收集统计信息,estimate_percent使用默认值       ...

  3. January 26 2017 Week 4 Thursday

    Wasting time is robbing yourself. 浪费时间就是掠夺自己. Wasting time is not only robbing yourself, moreover, i ...

  4. easyui学习笔记4—panel的实现

    这篇看看easyui是怎么实现panel的,就是类似一个容器,里面可以装具体内容或者其他的easyui控件. 1.这里先看看引用的资源文件 <link rel="stylesheet& ...

  5. 马云18年前制止偷井盖视频走红 2013-05-10 11:00:37 来源: 新快报(广州) 有0人参与 分享到 网易微博 新浪微博 腾讯空间 人人网 有道云笔记 在一次访谈中,即将卸任阿里巴巴CEO的马云自曝了他第一次上电视是在1995年。“我刚开始创

    马云18年前制止偷井盖视频走红 2013-05-10 11:00:37 来源: 新快报(广州) 有0人参与   分享到 网易微博 新浪微博 腾讯空间 人人网 有道云笔记 在一次访谈中,即将卸任阿里巴巴 ...

  6. 安装ale_python_interface时遇到make错误

    1. 首先按照https://pypi.org/project/ale-python-interface/0.0.1/来安装,直接python3 -m pip 但提示缺少一个头文件ale_c_wrap ...

  7. 【java基础】随手写的一个日期计算,新手可以看看

    随手写的一个例子, 只是练习下自己的代码布局以及思路.. 1. 先写下简单的测试 2. 根据常用的不用修改的变量抽取出来, 作为常量(常量的命名可能有点不规范,谅解~) 3. 方法的作用不一样, 抽取 ...

  8. 理解Underscore中的restArgs函数

    虽然Underscore并没有在API手册中提及到restArgs函数,我们仍然可以通过_.restArgs接口使用restArgs函数.如果不去阅读源码,我们很难发现Underscore中还有这样的 ...

  9. 连接IBM MQ原因码报2035的错误解决办法

    我们的系统使用了ibm mq,用户用来向国家局上报文件和接收文件,前几天用户说上报一直不成功.由于 开发这块程序的人已经辞职了,我觉定在我的机器部署一套,研究一下.我的思路: 在我的机器上安装mq,建 ...

  10. 模式:模版、样式;属于分类、识别的范围;分类、归类的标准-How are patterns obtained?

    模式及套路 模式:模版.样式:属于分类.识别的范围. How are patterns obtained? Through : re-use, classification and finally a ...