Linux字符设备驱动--No.1
- 平台: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的更多相关文章
- 深入理解Linux字符设备驱动
文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...
- Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】
本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...
- Smart210学习记录----beep linux字符设备驱动
今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈...但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决 ...
- Linux字符设备驱动实现
Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...
- Linux字符设备驱动基本结构
1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...
- (57)Linux驱动开发之三Linux字符设备驱动
1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...
- Linux字符设备驱动框架
字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...
- Linux 字符设备驱动模型
一.使用字符设备驱动程序 1. 编译/安装驱动 在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码.因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块 2. 创建设备文件 通 ...
- linux字符设备驱动学习笔记(一):简单的字符设备驱动
最近在鼓捣lnux字符设备驱动,在网上搜集的各种关于linux设备驱动的代码和注释,要么是针对2.4的,要么是错误百出,根本就不能运行成功,真希望大家在发博客的时候能认真核对下代码的正确性,特别是要把 ...
- Linux字符设备驱动
一.字符设备基础 字符设备 二.字符设备驱动与用户空间访问该设备的程序三者之间的关系 三.字符设备模型 1.Linux内核中,使用 struct cdev 来描述一个字符设备 动态申请(构造)cdev ...
随机推荐
- mysql io过高
背景: 晚上,公司业务群里发信息说,有玩家在游戏里面赠送别人礼物后,赠送记录在20多分钟以后才出现,延时太高. 问题: 公司数据库使用mysql,配置了主从.配置的是,游戏程序写数据到主库,读数据到从 ...
- 最短路径-Dijkstra算法与Floyd算法
一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1 ADE:2 ADCE:3 ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径 ...
- python .loc vs .iloc区别
1.loc意义:通过行标签索引行数据 例: loc[n]表示索引的是第n行(index 是整数) loc[‘d’]表示索引的是第’d’行(index 是字符) 2. .iloc :通过行号获取行数 ...
- [EffectiveC++]item36:绝不重新定义继承而来的non-virtual函数
- 分布式链路跟踪系统架构SkyWalking和zipkin和pinpoint
Net和Java基于zipkin的全链路追踪 https://www.cnblogs.com/zhangs1986/p/8966051.html 在各大厂分布式链路跟踪系统架构对比 中已经介绍了几大框 ...
- linux自动备份oracle数据库
#此脚本只备份数据表,而且为了方便恢复数据是做的单表逐个备份#在写脚本过程中遇到的报错均加入了解决方案的链接(虽然错误代码没有贴出来)#最终将在脚本所在目录生成年月日-时分的目录,目录下为表名.dmp ...
- [转] Java 命名规范
定义规范的目的是为了使项目的代码样式统一,使程序有良好的可读性. 包的命名 (全部小写,由域名定义) Java包的名字都是由小写单词组成.但是由于Java面向对象编程的特性,每一名Java程序员都 ...
- 记两个std接口equal_range,set_difference
1.equal_range equal_range是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下, ...
- scanf函数读取缓冲区数据的问题
标准I\O的缓冲类型 标准I\O根据不同的应用需求,提供了全缓冲.行缓冲.无缓冲三种缓冲方式. 全缓冲:只有当划定的缓冲区被填满或者数据读取至末尾时,才开始执行I\O操作(执行系统提供的read\wr ...
- Intellij IDEA 格式化代码