1. 平台:tiny210SOC:s5pv210内核:Linux 3.0.8字符驱动:按键中断驱动源码:
  1. /*****************************************************************************
  2. 简 述:简单字符型驱动程序,手动静态分配设备号,手动创建设备节点
  3. ******************************************************************************/
  4. #include <linux/module.h>
  5. #include <linux/moduleparam.h>
  6. #include <linux/cdev.h>
  7. #include <linux/fs.h>
  8. #include <linux/wait.h>
  9. #include <linux/poll.h>
  10. #include <linux/sched.h>
  11. #include <linux/irq.h>
  12. #include <asm/irq.h>
  13. #include <linux/interrupt.h>
  14.  
  15. #include <mach/map.h>
  16. #include <mach/gpio.h>
  17. #include <mach/regs-gpio.h>
  18. #include <plat/gpio-cfg.h>
  19.  
  20. #include <linux/slab.h>
  21.  
  22. #define DEVICE_NAME "buttons"
  23.  
  24. struct button_desc {
  25. int gpio;
  26. int number;
  27. char *name;
  28. };
  29.  
  30. static struct button_desc buttons[] = {
  31. { S5PV210_GPH2(), , "KEY0" },
  32. { S5PV210_GPH2(), , "KEY1" },
  33. { S5PV210_GPH2(), , "KEY2" },
  34. { S5PV210_GPH2(), , "KEY3" },
  35. { S5PV210_GPH3(), , "KEY4" },
  36. { S5PV210_GPH3(), , "KEY5" },
  37. { S5PV210_GPH3(), , "KEY6" },
  38. { S5PV210_GPH3(), , "KEY7" },
  39. };
  40. #define OK (0)
  41. #define ERROR (-1)
  42.  
  43. struct cdev *gDev;
  44. struct file_operations *gFile;
  45. dev_t devNum;
  46. unsigned ;
  47. ;
  48. ;
  49.  
  50. static irqreturn_t button_interrupt(int irq, void *dev_id)
  51. {
  52. struct button_desc *bdata = (struct button_desc *)dev_id;
  53.  
  54. int down;
  55. unsigned tmp;
  56.  
  57. tmp = gpio_get_value(bdata->gpio);
  58.  
  59. /* active low */
  60. down = !tmp;
  61. printk("KEY %d: %08x\n", bdata->number, down);
  62.  
  63. return IRQ_HANDLED;
  64. }
  65.  
  66. int butsOpen(struct inode *p, struct file *f)
  67. {
  68.  
  69. int irq;
  70. int i;
  71. ;
  72. printk(KERN_EMERG"butsOpen\r\n");
  73. ; i < ARRAY_SIZE(buttons); i++) {
  74. if (!buttons[i].gpio)
  75. continue;
  76.  
  77. irq = gpio_to_irq(buttons[i].gpio);
  78. err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,
  79. buttons[i].name, (void *)&buttons[i]);
  80. if (err)
  81. break;
  82. }
  83.  
  84. if (err) {
  85. i--;
  86. ; i--) {
  87. if (!buttons[i].gpio)
  88. continue;
  89.  
  90. irq = gpio_to_irq(buttons[i].gpio);
  91. disable_irq(irq);
  92. free_irq(irq, (void *)&buttons[i]);
  93. }
  94.  
  95. return -EBUSY;
  96. }
  97. ;
  98. }
  99.  
  100. int charDrvInit(void)
  101. {
  102.  
  103. devNum = MKDEV(reg_major, reg_minor);
  104.  
  105. printk(KERN_EMERG"devNum is %d\r\n", devNum);
  106. if(OK == register_chrdev_region(devNum, subDevNum, DEVICE_NAME))
  107. {
  108. printk(KERN_EMERG"register_chrdev_region ok\r\n");
  109. }
  110. else
  111. {
  112. printk(KERN_EMERG"register_chrdev_region error\r\n");
  113. return ERROR;
  114. }
  115. /*if(OK == alloc_chrdev_region(&devNum, subDevNum, subDevNum,"test"))
  116. {
  117. printk(KERN_EMERG"register_chrdev_region ok\r\n");
  118. }
  119. else
  120. {
  121. printk(KERN_EMERG"register_chrdev_region error\r\n");
  122. return ERROR;
  123. }*/
  124.  
  125. gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
  126. gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
  127.  
  128. gFile->open = butsOpen;
  129. //注册设备函数到file_operations结构体gFile
  130.  
  131. //gDev->owner = THIS_MODULE;
  132. gFile->owner = THIS_MODULE;
  133. cdev_init(gDev, gFile);
  134. //在cdev结构体中添加指针指向file_operations结构体gFile
  135. cdev_add(gDev, devNum, );
  136. //建立设备号与cdev结构体联系
  137. printk(KERN_EMERG"button driver initial done...\r\n");
  138. ;
  139. }
  140.  
  141. void __exit charDrvExit(void)
  142. {
  143. int i;
  144.  
  145. cdev_del(gDev);
  146. unregister_chrdev_region(devNum, subDevNum);
  147. return;
  148. }
  149. module_init(charDrvInit);
  150. module_exit(charDrvExit);
  151. MODULE_LICENSE("GPL");

  1. int butsOpen(struct inode *p, struct file *f)
  2. {
  3.  
  4. int irq;
  5. int i;
  6. ;
  7. printk(KERN_EMERG"butsOpen\r\n");
  8. ; i < ARRAY_SIZE(buttons); i++) {
  9. if (!buttons[i].gpio)
  10. continue;
  11.  
  12. irq = gpio_to_irq(buttons[i].gpio);
  13. err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,
  14. buttons[i].name, (void *)&buttons[i]);
  15. if (err)
  16. break;
  17. }
  18.  
  19. if (err) {
  20. i--;
  21. ; i--) {
  22. if (!buttons[i].gpio)
  23. continue;
  24.  
  25. irq = gpio_to_irq(buttons[i].gpio);
  26. disable_irq(irq);
  27. free_irq(irq, (void *)&buttons[i]);
  28. }
  29.  
  30. return -EBUSY;
  31. }
  32. ;
  33. }
  1. #define gpio_to_irq __gpio_to_irq
  1. int __gpio_to_irq(unsigned gpio)
  2. {
  3. struct gpio_chip *chip;
  4. chip = gpio_to_chip(gpio);
  5. return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
  6. }
  1. int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
  2. {
  3. struct s3c_gpio_chip *s3c_chip = container_of(chip,
  4. struct s3c_gpio_chip, chip);
  5.  
  6. return s3c_chip->irq_base + offset;
  7. }
  1. static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
  2. {
  3. return gpio_desc[gpio].chip;//此处的gpio_desc[gpio].chip实际完成赋值在gpio-s5pv210.c中的s5pv210_gpiolib_init(void)函数中实现
  4. }

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

  1. static __init int s5pv210_gpiolib_init(void)
  2. {
  3. struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
  4. int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
  5. ;
  6. ;
  7.  
  8. ; i < nr_chips; i++, chip++) {
  9. if (chip->config == NULL) {
  10. chip->config = &gpio_cfg;
  11. chip->group = gpioint_group++;
  12. }
  13. if (chip->base == NULL)
  14. chip->base = S5PV210_BANK_BASE(i);
  15. }
  16.  
  17. samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
  18. s5p_register_gpioint_bank(IRQ_GPIOINT, , S5P_GPIOINT_GROUP_MAXNR);
  19.  
  20. ;
  21. }
  1. static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
  2. {
  3. .chip = {
  4. .),
  5. .ngpio = S5PV210_GPIO_A0_NR,
  6. .label = "GPA0",
  7. },
  8. }, {
  9. .chip = {
  10. .),
  11. .ngpio = S5PV210_GPIO_A1_NR,
  12. .label = "GPA1",
  13. },
  14. }, {
  15. .chip = {
  16. .),
  17. .ngpio = S5PV210_GPIO_B_NR,
  18. .label = "GPB",
  19. },
  20. }, {
  21. .chip = {
  22. .),
  23. .ngpio = S5PV210_GPIO_C0_NR,
  24. .label = "GPC0",
  25. },
  26. }, {
  27. .chip = {
  28. .),
  29. .ngpio = S5PV210_GPIO_C1_NR,
  30. .label = "GPC1",
  31. },
  32. }, {
  33. .chip = {
  34. .),
  35. .ngpio = S5PV210_GPIO_D0_NR,
  36. .label = "GPD0",
  37. },
  38. }, {
  39. .chip = {
  40. .),
  41. .ngpio = S5PV210_GPIO_D1_NR,
  42. .label = "GPD1",
  43. },
  44. }, {
  45. .chip = {
  46. .),
  47. .ngpio = S5PV210_GPIO_E0_NR,
  48. .label = "GPE0",
  49. },
  50. }, {
  51. .chip = {
  52. .),
  53. .ngpio = S5PV210_GPIO_E1_NR,
  54. .label = "GPE1",
  55. },
  56. }, {
  57. .chip = {
  58. .),
  59. .ngpio = S5PV210_GPIO_F0_NR,
  60. .label = "GPF0",
  61. },
  62. }, {
  63. .chip = {
  64. .),
  65. .ngpio = S5PV210_GPIO_F1_NR,
  66. .label = "GPF1",
  67. },
  68. }, {
  69. .chip = {
  70. .),
  71. .ngpio = S5PV210_GPIO_F2_NR,
  72. .label = "GPF2",
  73. },
  74. }, {
  75. .chip = {
  76. .),
  77. .ngpio = S5PV210_GPIO_F3_NR,
  78. .label = "GPF3",
  79. },
  80. }, {
  81. .chip = {
  82. .),
  83. .ngpio = S5PV210_GPIO_G0_NR,
  84. .label = "GPG0",
  85. },
  86. }, {
  87. .chip = {
  88. .),
  89. .ngpio = S5PV210_GPIO_G1_NR,
  90. .label = "GPG1",
  91. },
  92. }, {
  93. .chip = {
  94. .),
  95. .ngpio = S5PV210_GPIO_G2_NR,
  96. .label = "GPG2",
  97. },
  98. }, {
  99. .chip = {
  100. .),
  101. .ngpio = S5PV210_GPIO_G3_NR,
  102. .label = "GPG3",
  103. },
  104. }, {
  105. .config = &gpio_cfg_noint,
  106. .chip = {
  107. .),
  108. .ngpio = S5PV210_GPIO_I_NR,
  109. .label = "GPI",
  110. },
  111. }, {
  112. .chip = {
  113. .),
  114. .ngpio = S5PV210_GPIO_J0_NR,
  115. .label = "GPJ0",
  116. },
  117. }, {
  118. .chip = {
  119. .),
  120. .ngpio = S5PV210_GPIO_J1_NR,
  121. .label = "GPJ1",
  122. },
  123. }, {
  124. .chip = {
  125. .),
  126. .ngpio = S5PV210_GPIO_J2_NR,
  127. .label = "GPJ2",
  128. },
  129. }, {
  130. .chip = {
  131. .),
  132. .ngpio = S5PV210_GPIO_J3_NR,
  133. .label = "GPJ3",
  134. },
  135. }, {
  136. .chip = {
  137. .),
  138. .ngpio = S5PV210_GPIO_J4_NR,
  139. .label = "GPJ4",
  140. },
  141. }, {
  142. .config = &gpio_cfg_noint,
  143. .chip = {
  144. .),
  145. .ngpio = S5PV210_GPIO_MP01_NR,
  146. .label = "MP01",
  147. },
  148. }, {
  149. .config = &gpio_cfg_noint,
  150. .chip = {
  151. .),
  152. .ngpio = S5PV210_GPIO_MP02_NR,
  153. .label = "MP02",
  154. },
  155. }, {
  156. .config = &gpio_cfg_noint,
  157. .chip = {
  158. .),
  159. .ngpio = S5PV210_GPIO_MP03_NR,
  160. .label = "MP03",
  161. },
  162. }, {
  163. .config = &gpio_cfg_noint,
  164. .chip = {
  165. .),
  166. .ngpio = S5PV210_GPIO_MP04_NR,
  167. .label = "MP04",
  168. },
  169. }, {
  170. .config = &gpio_cfg_noint,
  171. .chip = {
  172. .),
  173. .ngpio = S5PV210_GPIO_MP05_NR,
  174. .label = "MP05",
  175. },
  176. }, {
  177. .base = (S5P_VA_GPIO + 0xC00),
  178. .config = &gpio_cfg_noint,
  179. .irq_base = IRQ_EINT(),
  180. .chip = {
  181. .),
  182. .ngpio = S5PV210_GPIO_H0_NR,
  183. .label = "GPH0",
  184. .to_irq = samsung_gpiolib_to_irq,
  185. },
  186. }, {
  187. .base = (S5P_VA_GPIO + 0xC20),
  188. .config = &gpio_cfg_noint,
  189. .irq_base = IRQ_EINT(),
  190. .chip = {
  191. .),
  192. .ngpio = S5PV210_GPIO_H1_NR,
  193. .label = "GPH1",
  194. .to_irq = samsung_gpiolib_to_irq,
  195. },
  196. }, {
  197. .base = (S5P_VA_GPIO + 0xC40),
  198. .config = &gpio_cfg_noint,
  199. .irq_base = IRQ_EINT(),
  200. .chip = {
  201. .),
  202. .ngpio = S5PV210_GPIO_H2_NR,
  203. .label = "GPH2",
  204. .to_irq = samsung_gpiolib_to_irq,
  205. },
  206. }, {
  207. .base = (S5P_VA_GPIO + 0xC60),
  208. .config = &gpio_cfg_noint,
  209. .irq_base = IRQ_EINT(),
  210. .chip = {
  211. .),
  212. .ngpio = S5PV210_GPIO_H3_NR,
  213. .label = "GPH3",
  214. .to_irq = samsung_gpiolib_to_irq,
  215. },
  216. },
  217. };

struct s3c_gpio_chip s5pv210_gpio_4bit[]

  1. void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
  2. 2 int nr_chips)
  3. {
  4. ; nr_chips--, chip++) {
  5. samsung_gpiolib_add_4bit(chip);
  6. s3c_gpiolib_add(chip);
  7. }
  8. }
  1. __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
  2. {
  3. struct gpio_chip *gc = &chip->chip;//将struct s3c_gpio_chip结构体成员结构体chip赋值给struct gpio_chip结构体局部变量gc
  4. int ret;
  5.  
  6. BUG_ON(!chip->base);
  7. BUG_ON(!gc->label);
  8. BUG_ON(!gc->ngpio);
  9.  
  10. spin_lock_init(&chip->lock);
  11.  
  12. if (!gc->direction_input)
  13. gc->direction_input = s3c_gpiolib_input;
  14. if (!gc->direction_output)
  15. gc->direction_output = s3c_gpiolib_output;
  16. if (!gc->set)
  17. gc->set = s3c_gpiolib_set;
  18. if (!gc->get)
  19. gc->get = s3c_gpiolib_get;
  20.  
  21. #ifdef CONFIG_PM
  22. if (chip->pm != NULL) {
  23. if (!chip->pm->save || !chip->pm->resume)
  24. printk(KERN_ERR "gpio: %s has missing PM functions\n",
  25. gc->label);
  26. } else
  27. printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
  28. #endif
  29.  
  30. /* gpiochip_add() prints own failure message on error. */
  31. ret = gpiochip_add(gc);
  32. )
  33. s3c_gpiolib_track(chip);
  34. }
  1. int gpiochip_add(struct gpio_chip *chip)
  2. {
  3. unsigned long flags;
  4. ;
  5. unsigned id;
  6. int base = chip->base;
  7.  
  8. ))
  9. && ) {
  10. status = -EINVAL;
  11. goto fail;
  12. }
  13.  
  14. spin_lock_irqsave(&gpio_lock, flags);
  15.  
  16. ) {
  17. base = gpiochip_find_base(chip->ngpio);
  18. ) {
  19. status = base;
  20. goto unlock;
  21. }
  22. chip->base = base;
  23. }
  24.  
  25. /* these GPIO numbers must not be managed by another gpio_chip */
  26. for (id = base; id < base + chip->ngpio; id++) {
  27. if (gpio_desc[id].chip != NULL) {
  28. status = -EBUSY;
  29. break;
  30. }
  31. }
  32. ) {
  33. for (id = base; id < base + chip->ngpio; id++) {
  34. gpio_desc[id].chip = chip;//在这里gpio_desc[id].chip和struct s3c_gpio_chip建立联系
  35.  
  36. /* REVISIT: most hardware initializes GPIOs as
  37. * inputs (often with pullups enabled) so power
  38. * usage is minimized. Linux code should set the
  39. * gpio direction first thing; but until it does,
  40. * we may expose the wrong direction in sysfs.
  41. */
  42. gpio_desc[id].flags = !chip->direction_input
  43. ? ( << FLAG_IS_OUT)
  44. : ;
  45. }
  46. }
  47.  
  48. of_gpiochip_add(chip);
  49.  
  50. unlock:
  51. spin_unlock_irqrestore(&gpio_lock, flags);
  52.  
  53. if (status)
  54. goto fail;
  55.  
  56. status = gpiochip_export(chip);
  57. if (status)
  58. goto fail;
  59.  
  60. ;
  61. fail:
  62. /* failures here can mean systems won't boot... */
  63. pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",
  64. chip->,
  65. chip->label ? : "generic");
  66. return status;
  67. }

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. mysql io过高

    背景: 晚上,公司业务群里发信息说,有玩家在游戏里面赠送别人礼物后,赠送记录在20多分钟以后才出现,延时太高. 问题: 公司数据库使用mysql,配置了主从.配置的是,游戏程序写数据到主库,读数据到从 ...

  2. 最短路径-Dijkstra算法与Floyd算法

    一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径 ...

  3. python .loc vs .iloc区别

    1.loc意义:通过行标签索引行数据 例: loc[n]表示索引的是第n行(index 是整数) loc[‘d’]表示索引的是第’d’行(index 是字符) 2. .iloc   :通过行号获取行数 ...

  4. [EffectiveC++]item36:绝不重新定义继承而来的non-virtual函数

  5. 分布式链路跟踪系统架构SkyWalking和zipkin和pinpoint

    Net和Java基于zipkin的全链路追踪 https://www.cnblogs.com/zhangs1986/p/8966051.html 在各大厂分布式链路跟踪系统架构对比 中已经介绍了几大框 ...

  6. linux自动备份oracle数据库

    #此脚本只备份数据表,而且为了方便恢复数据是做的单表逐个备份#在写脚本过程中遇到的报错均加入了解决方案的链接(虽然错误代码没有贴出来)#最终将在脚本所在目录生成年月日-时分的目录,目录下为表名.dmp ...

  7. [转] Java 命名规范

    定义规范的目的是为了使项目的代码样式统一,使程序有良好的可读性. 包的命名  (全部小写,由域名定义) Java包的名字都是由小写单词组成.但是由于Java面向对象编程的特性,每一名Java程序员都 ...

  8. 记两个std接口equal_range,set_difference

    1.equal_range equal_range是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下, ...

  9. scanf函数读取缓冲区数据的问题

    标准I\O的缓冲类型 标准I\O根据不同的应用需求,提供了全缓冲.行缓冲.无缓冲三种缓冲方式. 全缓冲:只有当划定的缓冲区被填满或者数据读取至末尾时,才开始执行I\O操作(执行系统提供的read\wr ...

  10. Intellij IDEA 格式化代码