平台: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. RMAN备份等级详解

    (2011-06-27 11:38:28) 转载▼ 标签: 杂谈 分类: oracle 在rman增量备份中,有差异增量和累积增量的概念 1.概念 差异增量:是备份上级及同级备份以来所有变化的数据块, ...

  2. 关于单一网络适配器拓扑TMG

    单网络适配器拓扑的功能 在单网络适配器拓扑中可以实现有限的 Forefront TMG 功能,其中包括: 针对 HTTP.HTTPS 和 CERN 代理 FTP 的正向 (CERN) 代理(仅限下载) ...

  3. CSS position属性 标签: css 2016-09-06 15:58 78人阅读 评论(0) 收藏

    踩了position的坑,主要是因为对position属性理解不深. 以下是w3school中对position的解释: 可能的值 值 描述 absolute 生成绝对定位的元素,相对于 static ...

  4. shell-day1

    shell概述:这里说的是命令行shell,例如"bash/sh/ksh/csh"(Unix/Linux系统).cmd.exe命令提示字符(windwos系统),这里主要介绍Uni ...

  5. Hibernate初探之单表映射

    http://www.imooc.com/video/7816 1.什么是ORM?为什么使用Hibernate? 对象关系映射:为了少写和底层数据库相关的sql语句,方便程序的维护.修改,提高跨平台性 ...

  6. SQLi-db 批量注入工具+教程

    这款工具在中国还没人发.所以我发来给大家玩玩:顺便带了教程. 关键字:inurl:article.asp?id= inurl:article.php?id=inurl:article.jsp?id=( ...

  7. [由于远程方关闭传输流,身份验证失败]一次处理支付接口bug记录

    因公司系统升级,出现突然有些银行卡不能支付的情况,最开始排查发现是第三方平台接口返回有问题: 返回如下: 从11月7日下午开始一直联系第三方,第三方开始排查,一直说是数据格式有问题. 修改格式以后问题 ...

  8. poj2312 Battle City 【暴力 或 优先队列+BFS 或 BFS】

    题意:M行N列的矩阵.Y:起点,T:终点.S.R不能走,走B花费2,走E花费1.求Y到T的最短时间. 三种解法.♪(^∇^*) //解法一:暴力 //157MS #include<cstdio& ...

  9. perl的一些小函数——split、join、sort

    有时候,我们需要将一个字符串或一行文本通过某种方式转换为单个的元素存储在数组中,或者将许多元素通过某种分割符,将他们组合成一个字符串.perl刚好就提供了这样的功能,通过split或者join分割或组 ...

  10. 【[SCOI2008]奖励关】

    又抄了一篇题解 要凉了要凉了,开学了我还什么都不会 文化课凉凉,NOIP还要面临爆零退役的历史进程 这道题挺神的,期望+状态压缩 我们设\(dp[i][S]\)表示在第\(i\)天前,捡的宝物状态为\ ...