button_drv.c驱动文件:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>           //包含iomap函数iounmap函数
#include <asm/uaccess.h>         //包含copy_from_user函数
#include <linux/device.h>        //包含class类相关的处理函数
#include <linux/fs.h>           //包含file_operations结构体

#define DRIVER_NAME "button_drv"
#define DEVICE_NAME "button_dev"

int major;

static struct class *buttondrv_class;
static struct class_device *buttondrv_class_dev;

volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL;
volatile unsigned long *gpgcon = NULL;
volatile unsigned long *gpgdat = NULL;

static int button_drv_open(struct inode *inode, struct file *file)
{
  *gpfcon &= ~((0x3<<(0*2)) | (0x3<<(2*2)));
  *gpgcon &= ~((0x3<<(3*2)) | (0x3<<(11*2)));
  return 0;
}

static int button_drv_read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
  int ret;
  unsigned char keyVal[4];
  unsigned long keyVals;

  if(count!=sizeof(keyVal))
  {
    printk("button_drv_read error 1 \n");
  }

  keyVals = *gpfdat;
  keyVal[0] = ((keyVals>>0) & 1);
  keyVal[1] = ((keyVals>>2) & 1);
  keyVals = *gpgdat;
  keyVal[2] = ((keyVals>>3) & 1);
  keyVal[3] = ((keyVals>>11) & 1);
  
  ret = copy_to_user(userbuf, keyVal, sizeof(keyVal));
  if(ret<0)
  {
    printk("button_drv_read error 2 \n");
  }

  return sizeof(keyVal);
}

static struct file_operations button_drv_fops = {
  .owner = THIS_MODULE,
  .open = button_drv_open,
  .read = button_drv_read,
};

static int button_drv_init(void)
{
  major = register_chrdev(0, DRIVER_NAME, &button_drv_fops);

  buttondrv_class = class_create(THIS_MODULE, DEVICE_NAME);
  buttondrv_class_dev = class_device_create(buttondrv_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);

  gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
  gpfdat = gpfcon + 1;
  gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16);
  gpgdat = gpgcon + 1;
  return 0;
}

static void button_drv_exit(void)
{
  unregister_chrdev(major, DRIVER_NAME);
  class_device_unregister(buttondrv_class_dev);
  class_destroy(buttondrv_class);
  iounmap(gpfcon);
  iounmap(gpgcon);
}

module_init(button_drv_init);
module_exit(button_drv_exit);

MODULE_LICENSE("GPL");

Makefile文件:

obj-m += button_drv.o

KERN_DIR = /work/system/linux-2.6.22.6

all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
rm -rf *.o *.ko *.order *.symvers *.mod.c

button_app.c文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  int fd;
  int val;
  char *filename;
  unsigned char keyVal[4];

  filename = argv[1];
  fd = open(filename, O_RDWR);
  if(fd<0)
  {
    printf("can not open \n");
  }

  while(1)
  {
    read(fd, keyVal, sizeof(keyVal));
    if(!keyVal[0] || !keyVal[1] || !keyVal[2] || !keyVal[3])
    {
      printf("key pressed %d %d %d %d \n", keyVal[0], keyVal[1], keyVal[2], keyVal[3]);
    }
  }

  return 0;
}

编译生成button_drv.ko文件和button_app文件,运行:./button_app /dev/button_dev

Linux 驱动——Button驱动1的更多相关文章

  1. Linux 驱动——Button驱动7(Timer)消抖

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  2. Linux 驱动——Button驱动6(mutex、NBLOCK、O_NONBLOCK)互斥信号量、阻塞、非阻塞

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  3. Linux 驱动——Button驱动5(atomic)原子量

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  4. Linux 驱动——Button驱动4(fasync)异步通知

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  5. Linux 驱动——Button驱动3(poll机制)

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  6. Linux 驱动——Button驱动2

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  7. Linux GPIO键盘驱动开发记录_OMAPL138

    Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...

  8. linux块设备驱动之实例

    1.注册:向内核注册个块设备驱动,其实就是用主设备号告诉内核这个代表块设备驱动 sbull_major  =  register_blkdev(sbull_major, "sbull&quo ...

  9. Linux 视频设备驱动V4L2最常用的控制命令

    http://blog.csdn.net/shaolyh/article/details/6583226 Linux 视频设备驱动V4L2最常用的控制命令使用说明(1.02) 命令 功能 VIDIOC ...

随机推荐

  1. 第七届 蓝桥杯 方格填数 dfs

    如下的10个格子  填入0~9的数字.要求:连续的两个数字不能相邻. (左右.上下.对角都算相邻) 一共有多少种可能的填数方案? 请填写表示方案数目的整数. 注意:你提交的应该是一个整数,不要填写任何 ...

  2. mui底部选项卡切换实现

    MUI提供了两种webview和div模式,来实现底部选项卡切换 效果相同,div是在同一个页面实现所有切换块的页面,根据id导航,而webview是由多个页面组成,形成页面之间的来回跳转

  3. ES6/ES7/ES8常用特性和新特性

    转自:https://www.jianshu.com/p/9da4aa1c9970

  4. keras神经网络做简单的回归问题

    咸鱼了半个多月了,要干点正经事了. 最近在帮老师用神经网络做多变量非线性的回归问题,没有什么心得,但是也要写个博文当个日记. 该回归问题是四个输入,一个输出.自己并不清楚这几个变量有什么关系,因为是跟 ...

  5. 15、TypeScript-函数

    1.参数和返回值可以指定类型 2.可选参数:在参数上加上?,表示可选的,可传可不传 3.默认参数:如果你不传参数,默认为20,如果你传参,就是你传的参数 4.剩余参数:会把传进来的实参变成一个数组,可 ...

  6. 【转】10分钟就能学会的.NET Core配置

    .NET Core为我们提供了一套用于配置的API,它为程序提供了运行时从文件.命令行参数.环境变量等读取配置的方法.配置都是键值对的形式,并且支持嵌套,.NET Core还内建了从配置反序列化为PO ...

  7. Windows编译安装使用cephfs客户端

    本文介绍如何将cephfs映射到windows的一个盘上,以磁盘映射的方式访问cephfs. 1.下载必要安装包 tdm-gcc:(安装时选32位)https://sourceforge.net/pr ...

  8. [CentOS] 环境变量设置的三种方法

    在CentOS系统中添加环境变量的方法有几种,推荐第三种方法.这里以添加 TexLive 2017 的环境变量为例进行说明. 1. 修改  ~/.bash_profile  文档,在文末添加以下代码: ...

  9. UVa 11389 - The Bus Driver Problem 难度:0

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  10. [BZOJ1596]电话网络

    Problem 给你一棵树,可以在每个点上选择造塔或不造,每座塔可以覆盖这个节点和相邻节点,问覆盖整棵树的最小塔数. Solution 看到这道题的第一眼,我就觉得是一题贪心题,但看见出题的时候分类在 ...