参考博客:https://blog.csdn.net/u011913612/article/details/52516303?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.channel_param

1.驱动程序

frist_driver.c

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <asm/uaccess.h>
#include <asm/io.h>#define HELLOON               1
#define HELLOOFF              0
#define HELLO_CNT             1
#define HELLO_NAME           "hello driver"static char readbuf[100];
static char writebuf[100];
static char kerneldata[] = {"hello my first driver"};
static char mybuf[100]   ="1234";struct hello_driver
{dev_t           devid;            /*设备号*/struct cdev     cdev;             /*cdev*/struct class    *class;           /*类*/struct device   *device;          /*设备*/int             major;            /*主设备号*/int             minor;            /*次设备号*/atomic_t        atomic_lock;      /*原子变量*/
};struct hello_driver hello_driver_dev;static ssize_t show_my_device(struct device *dev,struct device_attribute *attr, char *buf)
{return sprintf(buf, "%s\n", mybuf);
}static ssize_t set_my_device(struct device *dev,struct device_attribute *attr, const char *buf, size_t len)//echo命令时,将会调用该函数
{sprintf(mybuf, "%s", buf);return len;
}static DEVICE_ATTR(my_device_test, S_IWUSR|S_IRUSR, show_my_device, set_my_device);//定义一个名字为my_device_test的设备属性文件static int hello_driver_open(struct inode *inode, struct file *filp)
{if(!atomic_dec_and_test(&hello_driver_dev.atomic_lock)){atomic_inc(&hello_driver_dev.atomic_lock);return -EBUSY;           }filp->private_data = &hello_driver_dev;return 0;
}static ssize_t hello_driver_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{int ret = 0;memcpy(readbuf,kerneldata,sizeof(kerneldata));ret = copy_to_user(buf,readbuf,cnt);if(ret == 0){printk("kernel senddata ok!\n");}else{printk("kernel senddata failed\n");}return 0;
}static ssize_t hello_driver_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{int ret = 0;ret = copy_from_user(writebuf,buf,cnt);if(ret == 0){printk("kernel recvdata %s\n",writebuf);}else{printk("kernel recvdata failed\n");}return 0;
}static long hello_driver_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{switch(cmd){case HELLOON:  printk("Open hello driver\n");break;case HELLOOFF:   printk("Close hello driver\n");break;default:break;}return 0;
}static int hello_driver_release(struct inode *inode, struct file *filp)
{struct hello_driver *dev = filp->private_data;atomic_inc(&dev->atomic_lock);return 0;
}static struct file_operations hello_driver_fops= {.owner             = THIS_MODULE,.open              = hello_driver_open, .read              = hello_driver_read,.write             = hello_driver_write,.unlocked_ioctl    = hello_driver_unlocked_ioctl,.release           = hello_driver_release,
};static int __init hello_driver_init(void)
{int ret;/*1.设置原子变量,保证同一时刻只能有一个应用程序使用该驱动*/atomic_set(&hello_driver_dev.atomic_lock,1);/*2.分配设备号*//*2.1 之前分配了主设备号*/if(hello_driver_dev.major){/*注册设备号*/hello_driver_dev.devid = MKDEV(hello_driver_dev.major,0);ret = register_chrdev_region(hello_driver_dev.devid, HELLO_CNT, HELLO_NAME);if(ret < 0){printk("can't register major\n");  return ret; }}else/*2.2 之前未分配设备号,向内核申请设备号*/{alloc_chrdev_region(&hello_driver_dev.devid, 0, HELLO_CNT, HELLO_NAME); }printk(KERN_ERR"hello_driver_dev major = %d, minor = %d\n", hello_driver_dev.major,hello_driver_dev.minor);hello_driver_dev.cdev.owner = THIS_MODULE;cdev_init(&hello_driver_dev.cdev,&hello_driver_fops);ret = cdev_add(&hello_driver_dev.cdev, hello_driver_dev.devid,HELLO_CNT);if(ret){printk("Error cdev_add\n");  goto fail_to_cdev_add;}hello_driver_dev.class = class_create(THIS_MODULE,HELLO_NAME);if(IS_ERR(hello_driver_dev.class)){goto fail_to_class_create;}hello_driver_dev.device = device_create(hello_driver_dev.class , NULL, hello_driver_dev.devid, NULL, HELLO_NAME);if(IS_ERR(hello_driver_dev.device)){goto fail_to_device_create;}if(sysfs_create_file(&hello_driver_dev.device ->kobj), &dev_attr_my_device_test.attr))
{    //在mytest_device设备目录下创建一个my_device_test属性文件return -1;
}return 0;fail_to_cdev_add:unregister_chrdev_region(hello_driver_dev.devid, HELLO_CNT); return -1;
fail_to_class_create:cdev_del(&hello_driver_dev.cdev);unregister_chrdev_region(hello_driver_dev.devid, HELLO_CNT);return -1;
fail_to_device_create:cdev_del(&hello_driver_dev.cdev);unregister_chrdev_region(hello_driver_dev.devid, HELLO_CNT); class_destroy(hello_driver_dev.class);return -1;
}static void __exit hello_driver_exit(void)
{cdev_del(&hello_driver_dev.cdev);unregister_chrdev_region(hello_driver_dev.devid, HELLO_CNT); device_destroy(hello_driver_dev.class, hello_driver_dev.devid); class_destroy(hello_driver_dev.class);
}module_init(hello_driver_init);
module_exit(hello_driver_exit);
MODULE_DESCRIPTION("my hello driver");
MODULE_AUTHOR("Kong Lingze");
MODULE_LICENSE("GPL");

2.加载驱动程序编译到内核

添加文件夹

在kernel/driver目录下添加新的文件夹frist_driver,在frist_driver中添加文件Kconfig,Makefile,frist_driver.c


frist_driver/Kconfig中的内容:

frist_driver/Makefile中的内容:

在driver/Kconfig添加内容:

在driver/Makefile添加内容:

  • 在kernel/driver下执行make menuconfig,选择First Android Driver
  • 在安卓源码目录目录下source build/envsetup.sh
  • lunch xx xxxx (可选择)
  • make bootimage -j32

测试:

执行fastboot flash boot boot.img将内核烧写到开发板,在开发板目录找到sys/class/hello driver/hello driver或者下图目录,执行如图的命令

测试成功

3.用c程序进行测试

首先在android源码的packages目录下新建一个helloapp目录,该目录下新建hello_app.c和Android.mk两个文件。

hello_app.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>#define READ           3
#define WRITE          4
#define HELLO_ON       1
#define HELLO_OFF      0// ./app /dev/hello\driver  <cmd>
static unsigned char cUserData[] = {"User data"};
int main(int argc, char **argv)
{int  iFd;int  iRet;char *cFilename;unsigned int  arg = 0;unsigned char cReadBuf[100];unsigned char cWriteBuf[100];if(argc!=3){Printf(“Usage:%s <file inode> <cmd>”,argv[0]);}//打开设备结点cFilename = argv[1];iFd = open(cFilename, O_RDWR);if(iFd < 0){printf(" open %s failed\n", cFilename);return -1;}/*读取驱动中的数据*/if(atoi(argv[2]) == READ){memset(cReadBuf,sizeof(cReadBuf),sizeof(cReadBuf));iRet = read(iFd,cReadBuf,sizeof(cReadBuf));if(iRet < 0){printf("read %s data failed\n",cFilename);return -1;}else{printf("read data is:%s\n",cReadBuf);}}else if(atoi(argv[2]) == WRITE)//向驱动中写数据{memset(cWriteBuf,sizeof(cWriteBuf),sizeof(cWriteBuf));memcpy(cWriteBuf,cUserData,sizeof(cUserData));iRet = write(iFd,cWriteBuf,sizeof(cWriteBuf));if(iRet < 0){printf("write %s data failed\n",cFilename);return -1;}}else if(atoi(argv[2]) == HELLO_ON)//给驱动发送HELLO_ON命令{ioctl(iFd,HELLO_ON,arg);}else if(atoi(argv[2]) == HELLO_OFF)//给驱动发送HELLO_OFF命令{ioctl(iFd,HELLO_OFF,arg);}iRet = close(iFd);if(iFd < 0){printf("close %s failed",cFilename);return -1;}return 0;
}

Andoird.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := hellotest
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)

编译

完成之后在安卓源码目录,输入source build\envser.up.sh,再进入packages/helloapp目录执行mm命令,生成可执行文件,编译后的文件在out/target/product/xxx/obj/EXECUTABLES/hellotapp_intermediates/中

测试

adb shell
adb push hello_app /data把hello_app推送到android设备的data目录下,
chmod +x helloapp添加可执行权限。
执行./helloapp /dev/hello driver 1

打印如下:
Open hello driver
可见测试成功。

1.安卓访问驱动-实现简单驱动相关推荐

  1. [设备驱动] 最简单的内核设备驱动--字符驱动

    [设备驱动] 最简单的内核设备驱动--字符驱动  概要: x86平台上(linux-2.6.34.14;Linux debian 3.2.0-3-686-pae)编写一个256字节的字符驱动程序.在/ ...

  2. 黑苹果Yosemite 10.10.1懒人版完美安装及简单驱动设置

    原文地址为: 黑苹果Yosemite 10.10.1懒人版完美安装及简单驱动设置 1.硬件概要 CPU: 英特尔 Xeon E3-1230 V2 (四核) 主板: 技嘉 H77-DS3H (Intel ...

  3. RE0:从零开始的服务器生活(一):双硬盘双系统+无线网卡驱动+最简单的Ubuntu16.04 Nvidia显卡驱动设置

    目录 (一)双硬盘双系统+无线网卡驱动+Nvidia显卡驱动 前期的硬件准备 安装系统 准备Ubuntu驱动 网卡驱动 显卡驱动 必备软件安装 后记: (一)双硬盘双系统+无线网卡驱动+Nvidia显 ...

  4. 从零开始学Linux内核驱动--(二)简单内核模块驱动程序

    Linux驱动–(二)简单的内核模块驱动程序 一.概述 Linux中所有的驱动都是以内核模块的形式来实现的,他们与其他所有的内核编译在一起形成一个单独的内核镜像文件(所以说Linux是一个宏内核).当 ...

  5. 安卓驱动和linux驱动有什么不同

    安卓系统可以认为是定制化的linux系统. 因而安卓驱动就是linux驱动. 相对通常所说linux系统,安卓系统多了安卓专有驱动,多了JAVA虚拟机,JAVA虚拟机,虚拟机上的应用框架和框架之上的应 ...

  6. html调用服务器串口,【1768】串口驱动HTML简单的网页服务器演示

    本帖最后由 donatello1996 于 2019-3-31 20:23 编辑 [1768]串口驱动&HTML简单的网页服务器演示 之前忙于别的事情没空发帖,今晚都补回来,不多说废话. 得益 ...

  7. 不要驱动,简单粗暴的用树莓派驱动USB打印机

    不要驱动,简单粗暴的用树莓派驱动USB打印机 admin 2015年4月14日   5 Comments 网上很多文章都是再说如何用树莓派来做一个通用打印服务器,但是在很多应用场景下,配置CUPS什么 ...

  8. linux的驱动开发——简单驱动程序编写

    1.字符设备驱动介绍 \qquad字符设备驱动是linux驱动中,最基本的一类设备驱动,字符设备就是按照一个字节一个字节的方式进行读写操作的设备.读写数据分先后顺序,我们常见的单片机外设,比如led灯 ...

  9. Linux主机驱动与外设驱动分离思想

    - by 宋宝华(Barry Song) 1主机.外设驱动分离的意义 在Linux设备驱动框架的设计中,除了有分层设计实现以外,还有分隔的思想.举一个简单的例子,假设我们要通过SPI总线访问某外设,在 ...

最新文章

  1. vb中可视对象的操作
  2. Ubuntu 系统输入法设置
  3. sql数据库的基本操作
  4. Java比以往任何时候都摇滚
  5. java 树的数据结构_Java数据结构之树(二叉树)
  6. 深入源码,深度解析Java 线程池的实现原理
  7. python之rabbitMQ
  8. 2018上半年游戏行业DDoS态势报告
  9. 银河麒麟桌面操作系统中获取硬盘序列号
  10. CAD教程:CAD自定义菜单和工具栏的操作技巧
  11. NVR和DVR有什么区别_NVR和DVR哪个好 IP Camera
  12. DIN数据电缆行业现状调研及趋势分析报告
  13. 设置计算机每天定时自动开关机,如何设置电脑定时自动关机?
  14. 【预测模型】基于天牛须算法BAS优化BP神经网络实现数据预测matlab代码
  15. 如何在微信分享的网页中显示描述和图片
  16. 微信ios接入-Objc -all_load的坑
  17. 汇编语言(第三版)第十章 CALL 和 RET 指令 笔记
  18. MCM/ICM(美国大学生数学建模竞赛)报名指南
  19. 记录宝塔面板后台提示“拒绝了我们的连接请求”
  20. PAT乙级|C语言|1032 挖掘机技术哪家强 (20分)

热门文章

  1. c#设计模式——迭代器模式
  2. CUCM实现黑名单功能
  3. UVA 10003 Cutting Sticks
  4. 计算机语言各领域,香港大学计算机专业介绍
  5. 数模IC设计笔试面试100真题
  6. 中科曙光成为深交所技术产品联盟首批成员
  7. android 语言随sim变,如何修改Sim卡语言自适应
  8. wiremock使用入门
  9. 护眼台灯哪个品牌更好?2022护眼台灯品牌排行榜
  10. 地理位置服务(Location Service)