欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

Android驱动开发-第一个安卓驱动程序

程序员文章站 2022-03-11 16:29:13
1.驱动程序frist_driver.c#include #include static int __init first_drv_init(void){ printk("first_drv_init\n"); return 0;}static void __exit first_drv_exit(void){ printk("first_drv_exit\n");} m...

参考博客: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

Android驱动开发-第一个安卓驱动程序
frist_driver/Kconfig中的内容:
Android驱动开发-第一个安卓驱动程序

frist_driver/Makefile中的内容:
Android驱动开发-第一个安卓驱动程序
在driver/Kconfig添加内容:
Android驱动开发-第一个安卓驱动程序
在driver/Makefile添加内容:
Android驱动开发-第一个安卓驱动程序

  • 在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或者下图目录,执行如图的命令
Android驱动开发-第一个安卓驱动程序
测试成功

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/中
Android驱动开发-第一个安卓驱动程序

测试

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

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

本文地址:https://blog.csdn.net/weixin_43824344/article/details/107915758

相关标签: Android驱动开发