您好,登錄后才能下訂單哦!
這篇文章主要介紹了Android怎么開發(fā)第一個(gè)驅(qū)動(dòng)程序的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Android怎么開發(fā)第一個(gè)驅(qū)動(dòng)程序文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
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; /*設(shè)備號(hào)*/struct cdev cdev; /*cdev*/struct class *class; /*類*/struct device *device; /*設(shè)備*/int major; /*主設(shè)備號(hào)*/int minor; /*次設(shè)備號(hào)*/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命令時(shí),將會(huì)調(diào)用該函數(shù){sprintf(mybuf, "%s", buf);return len;}static DEVICE_ATTR(my_device_test, S_IWUSR|S_IRUSR, show_my_device, set_my_device);//定義一個(gè)名字為my_device_test的設(shè)備屬性文件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.設(shè)置原子變量,保證同一時(shí)刻只能有一個(gè)應(yīng)用程序使用該驅(qū)動(dòng)*/atomic_set(&hello_driver_dev.atomic_lock,1);/*2.分配設(shè)備號(hào)*//*2.1 之前分配了主設(shè)備號(hào)*/if(hello_driver_dev.major){/*注冊(cè)設(shè)備號(hào)*/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 之前未分配設(shè)備號(hào),向內(nèi)核申請(qǐng)?jiān)O(shè)備號(hào)*/{ 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設(shè)備目錄下創(chuàng)建一個(gè)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");
在kernel/driver目錄下添加新的文件夾frist_driver,在frist_driver中添加文件Kconfig,Makefile,frist_driver.c
frist_driver/Kconfig中的內(nèi)容:
frist_driver/Makefile中的內(nèi)容:
在driver/Kconfig添加內(nèi)容:
在driver/Makefile添加內(nèi)容:
在kernel/driver下執(zhí)行make menuconfig,選擇First Android Driver
在安卓源碼目錄目錄下source build/envsetup.sh
lunch xx xxxx (可選擇)
make bootimage -j32
執(zhí)行fastboot flash boot boot.img將內(nèi)核燒寫到開發(fā)板,在開發(fā)板目錄找到sys/class/hello driver/hello driver或者下圖目錄,執(zhí)行如圖的命令
測(cè)試成功
首先在android源碼的packages目錄下新建一個(gè)helloapp目錄,該目錄下新建hello_app.c和Android.mk兩個(gè)文件。
#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]);}//打開設(shè)備結(jié)點(diǎn)cFilename = argv[1];iFd = open(cFilename, O_RDWR);if(iFd < 0){printf(" open %s failed\n", cFilename);return -1;}/*讀取驅(qū)動(dòng)中的數(shù)據(jù)*/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)//向驅(qū)動(dòng)中寫數(shù)據(jù){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)//給驅(qū)動(dòng)發(fā)送HELLO_ON命令{ioctl(iFd,HELLO_ON,arg);}else if(atoi(argv[2]) == HELLO_OFF)//給驅(qū)動(dòng)發(fā)送HELLO_OFF命令{ioctl(iFd,HELLO_OFF,arg);} iRet = close(iFd);if(iFd < 0){printf("close %s failed",cFilename);return -1;}return 0;}
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,再進(jìn)入packages/helloapp目錄執(zhí)行mm命令,生成可執(zhí)行文件,編譯后的文件在out/target/product/xxx/obj/EXECUTABLES/hellotapp_intermediates/中
adb shell adb push hello_app /data把hello_app推送到android設(shè)備的data目錄下, chmod +x helloapp添加可執(zhí)行權(quán)限。 執(zhí)行./helloapp /dev/hello driver 1
打印如下:
Open hello driver
可見測(cè)試成功。
關(guān)于“Android怎么開發(fā)第一個(gè)驅(qū)動(dòng)程序”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Android怎么開發(fā)第一個(gè)驅(qū)動(dòng)程序”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。