MTK Android添加驅(qū)動(dòng)模塊講述_第1頁(yè)
MTK Android添加驅(qū)動(dòng)模塊講述_第2頁(yè)
MTK Android添加驅(qū)動(dòng)模塊講述_第3頁(yè)
MTK Android添加驅(qū)動(dòng)模塊講述_第4頁(yè)
MTK Android添加驅(qū)動(dòng)模塊講述_第5頁(yè)
已閱讀5頁(yè),還剩23頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、 1編寫linux驅(qū)動(dòng)程序1.1一、編寫驅(qū)動(dòng)核心程序1.2二、配置Kconfig1.3三、配置Makefile1.4四、配置系統(tǒng)的autoconfig1.5五、編譯 2編寫hal模塊2.1一、新建xxx.h文件2.2二、新建xxx.c文件2.2.11、包含相關(guān)頭文件和定義相關(guān)結(jié)構(gòu)2.2.22、定義hello_device_open函數(shù)2.2.33、定義自定義的api函數(shù)2.3三、在hello目錄下新建Android.mk文件2.4四、編譯、重新打包Android系統(tǒng)鏡像system.img3編寫jni3.1一、新建com_android_server_HelloService.cpp文件3.1

2、.11、包括頭文件3.1.22、編寫jni接口3.1.33、定義jni加載函數(shù),注冊(cè)jni方法表3.2二、修改onload.cpp,使系統(tǒng)啟動(dòng)時(shí)自動(dòng)加載JNI方法調(diào)用表3.3三、修改Android.mk文件,添加編譯路徑3.4四、編譯和重新生成system.img 4編寫Framework接口4.1一、定義通信接口4.1.11、新增接口文件4.1.22、添加編譯路徑4.1.33、編譯接口文件4.2二、建立java文件,編寫Framework接口4.3三、在ServerThread:run函數(shù)中增加加載代碼4.4四、編譯、重新打包system.img5App訪問編寫linux驅(qū)動(dòng)程序編寫驅(qū)動(dòng)核心

3、程序這里說的驅(qū)動(dòng)核心程序是指運(yùn)行在內(nèi)核空間的,完全按linux驅(qū)動(dòng)格式編寫的,基本上與android沒什么關(guān)系,一般包括xxx.h和xxx.c文件。進(jìn)入到kernel/drivers目錄,新建snsled目錄,然后建立對(duì)應(yīng)的snsled.h和snsled.c文件:/snsled.h#ifndef _SNSLED_H_#define _SNSLED_H_#define SNSLED_NUM (1)#define SNSLED_CLASS_NAME snsled#define SNSLED_DEVICE_NAMEsnsled#define SNSLED_NODE_NAME snsled#defin

4、e SNSLED_PROC_NAMEsnsled#define SNSLED_IOC_MAGIC k#define SNSLED_IO_ON 2323/_IO(SNSLED_IOC_MAGIC, 0)#define SNSLED_IO_OFF 2324/_IO(SNSLED_IOC_MAGIC, 1)#define SNSLED_IOW_PWM 2325/_IOW(SNSLED_IOC_MAGIC, 2, int)#define SNSLED_IOR_PWM 232/_IOR(SNSLED_IOC_MAGIC, 3, int)struct snsled_cntx int r1; struct

5、semaphore sem; struct cdev cdev;#endif/snsled.c#include #include #include #include /* printk() */#include /* kmalloc() */#include /* everything. */#include /* error codes */#include /* size_t */#include #include /* O_ACCMODE */#include #include #include /* cli(), *_flags */#include /* copy_*_user */

6、#include /* semaphore */#include #include /*class_create*/ #include snsled.h/* local definitions */*#include #include #include #include #include #include #include #include #include #include #include */#if defined (CONFIG_ARCH_MT6573)#include #include #include #elif defined (CONFIG_ARCH_MT6516)#inclu

7、de #include #endif/*=macros=*/#define BUF_SIZE (64)#define SNS_LED_CONTROL_LINEGPIO99/GPIO39#define SNS_LED_CONTROL_LINE_GPIO_MODEGPIO_MODE_00#define SNS_LED_CONTROL_LINE_PWM_MODEGPIO_MODE_01/*=declares=*/ssize_t snsled_read(struct file *filp, char _user *buf, size_t count, loff_t *f_pos);ssize_t sn

8、sled_write(struct file *filp, const char _user *buf, size_t count, loff_t *f_pos);long snsled_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);int snsled_open(struct inode *inode, struct file *filp);int snsled_release(struct inode *inode, struct file *filp);int snsled_turn_on(v

9、oid);int snsled_turn_off(void);int snsled_set_pwm(int arg);/*=global=*/static int g_snsled_major = 0;static int g_snsled_minor = 0;struct snsled_cntx *g_snsled_ptr = NULL;struct class *g_snsled_class = 0;static struct file_operations g_snsled_fops = .owner = THIS_MODULE, .read = snsled_read, .write

10、= snsled_write, .unlocked_ioctl = snsled_unlocked_ioctl, .open = snsled_open, .release = snsled_release,;/*=implements=*/ssize_t snsled_read(struct file *filp, char _user *buf, size_t count, loff_t *f_pos) #if 1 printk(KERN_ALERT Snsled read.n);#else char tmp_buf512 = 0; int len =sprintf(tmp_buf, sn

11、sled read.n); if (copy_to_user(buf, tmp_buf, count) /do nothing#endif return 0;ssize_t snsled_write(struct file *filp, const char _user *buf, size_t count, loff_t *f_pos) printk(KERN_ALERT Snsled write.n); return count;long snsled_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg

12、) int err = 0; long retval = 0;printk(KERN_ALERT Snsled ioctl:cmd=%d, arg=%d.n, cmd, arg);/*/extract the type and number bitfields, and dont decode/wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()if (_IOC_TYPE(cmd) != SNSLED_IOC_MAGIC) return -ENOTTY;/if (_IOC_NR(cmd) SNSLED_IOC_MA

13、XNR) return -ENOTTY;/to verify *arg is in user spaceif (_IOC_DIR(cmd) & _IOC_READ)err = !access_ok(VERIFY_WRITE, (void _user *)arg, _IOC_SIZE(cmd);else if (_IOC_DIR(cmd) & _IOC_WRITE)err = !access_ok(VERIFY_READ, (void _user *)arg, _IOC_SIZE(cmd);if (err) return -EFAULT; */ switch(cmd) case SNSLED_I

14、O_ON: printk(KERN_ALERT Snsled ioctl:on.n);/if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ONE)printk(Snsled set gpio failed! n);snsled_turn_on(); break; case SNSLED_IO_OFF: printk(KERN_ALERT Snsled ioctl:off.n);/if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)printk(Snsled set gpio failed!

15、n);snsled_turn_off(); break; case SNSLED_IOW_PWM: printk(KERN_ALERT Snsled ioctl:set pwm, arg=%d.n, arg); /retval = _get_user(g_snsled_ptr-r1, (int _user *)arg); snsled_set_pwm(int _user *)arg); break; case SNSLED_IOR_PWM: #if 0 retval = _put_user(g_snsled_ptr-r1, (int _user *)arg); printk(KERN_ALER

16、T Snsled ioctl:read r1:%i.n, g_snsled_ptr-r1);#endifprintk(KERN_ALERT Snsled ioctl:read pwm - not configured yet.n); break; default: printk(KERN_ALERT Snsled ioctl:you got the wrong command.n); break; return retval;int snsled_open(struct inode *inode, struct file *filp) printk(KERN_ALERT Snsled: sns

17、led_open.n);#if 0 if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_GPIO_MODE)printk(Snsled set gpio mode failed! n); if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)printk(Snsled set gpio dir failed! n); if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ONE)printk(Snsled set gpio fa

18、iled! n);#endif return 0;int snsled_release(struct inode *inode, struct file *filp) printk(KERN_ALERT Snsled: snsled_release.n);#if 0 if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_GPIO_MODE)printk(Snsled set gpio mode failed! n); if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)p

19、rintk(Snsled set gpio dir failed! n); if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)printk(Snsled set gpio failed! n);#endif return 0;int snsled_turn_on(void) printk(KERN_ALERT Snsled: snsled_turn_on.n); if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_PWM_MODE)printk(Snsled set

20、 gpio mode failed! n); if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)printk(Snsled set gpio dir failed! n); if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)printk(Snsled set gpio failed! n);return 0;int snsled_turn_off(void) printk(KERN_ALERT Snsled: snsled_turn_off.n); if(mt_set_gpio_m

21、ode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_GPIO_MODE)printk(Snsled set gpio mode failed! n); if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)printk(Snsled set gpio dir failed! n); if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)printk(Snsled set gpio failed! n);return 0;/for old mode/*

22、struct _PWM_OLDMODE_REGS U16 IDLE_VALUE; /0U16 GUARD_VALUE;/0U16 GDURATION;/U16 WAVE_NUM;/0U16 DATA_WIDTH;/high level, 13bits, 08191U16 THRESH;/tPWM_MODE_OLD_REGS;*/int snsled_set_pwm(int arg) struct pwm_spec_config pwm_setting;pwm_setting.pwm_no = PWM1;printk(KERN_ALERT Snsled: snsled_open begin.n)

23、;pwm_setting.mode = PWM_MODE_OLD;pwm_setting.clk_div = CLK_DIV16;/CLK_DIV128;pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K;pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE = 0;pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE = 0;pwm_setting.PWM_MODE_OLD_REGS.GDURATION = 8100;pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM = 0

24、;pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 8100;pwm_setting.PWM_MODE_OLD_REGS.THRESH = 8100;pwm_set_spec_config(&pwm_setting);printk(KERN_ALERT Snsled: snsled_open done.n);return 0;/alloc device majorstatic int vircdex_alloc_major(void) dev_t devt = 0; int result = 0; result = alloc_chrdev_region(&

25、devt, g_snsled_minor, SNSLED_NUM, SNSLED_NODE_NAME); g_snsled_major = MAJOR(devt); return result;static int snsled_release_major(void) dev_t devt = MKDEV(g_snsled_major, g_snsled_minor); unregister_chrdev_region(devt, 1); return 0;static int snsled_setup_dev(struct snsled_cntx *dev) int err, devno =

26、 MKDEV(g_snsled_major, g_snsled_minor); cdev_init(&(dev-cdev), &g_snsled_fops); dev-cdev.owner = THIS_MODULE; err = cdev_add(&dev-cdev, devno, 1); if(err) return err; /init_MUTEX(&(dev-sem); sema_init(&(dev-sem), 1); return 0;static int snsled_unsetup_dev(struct snsled_cntx *dev) cdev_del(&(dev-cdev

27、); return 0;static int snsled_create_devfiles(dev_t devt) /, const struct device_attribute *attr) int err = -1; struct device *dev = NULL; g_snsled_class = class_create(THIS_MODULE, SNSLED_CLASS_NAME); if(IS_ERR(g_snsled_class) err = PTR_ERR(g_snsled_class); printk(KERN_ALERT Failed to create class.

28、n); goto CLASS_CREATE_ERR; dev = device_create(g_snsled_class, NULL, devt, NULL, SNSLED_DEVICE_NAME); /dev = device_create(hello_class, NULL, dev, %s, HELLO_DEVICE_FILE_NAME); /device_create( my_class, NULL, MKDEV(hello_major, 0), hello %d, 0 ); /dev = device_create(g_snsled_class, NULL, MKDEV(MYDRI

29、VER_Major, 0), NULL, DEVICE_NAME); if(IS_ERR(dev) err = PTR_ERR(dev); printk(KERN_ALERT Failed to create device.n); goto DEVICE_CREATE_ERR; /*err = device_create_file(dev, attr); if(err err) printk(KERN_ALERTalloc major failed.n); goto ALLOC_MAJOR_ERR; devt = MKDEV(g_snsled_major, g_snsled_minor); /

30、2 device object init g_snsled_ptr = kmalloc(sizeof(struct snsled_cntx), GFP_KERNEL); if(!g_snsled_ptr) err = -ENOMEM; printk(KERN_ALERTkmalloc failed.n); goto KMALLOC_ERR; memset(g_snsled_ptr, 0, sizeof(struct snsled_cntx); /3 setup device err = snsled_setup_dev(g_snsled_ptr); if(0 err) printk(KERN_

31、ALERTdevice setup failed.n); goto DEVICE_SETUP_ERR; /4 create files in directory /dev/ and /sys/ /err = snsled_create_devfiles(devt, attr); err = snsled_create_devfiles(devt); if(0 err) printk(KERN_ALERTdevfiles create failed.n); goto DEVFILES_CREATE_ERR; /5 create proc file err = snsled_create_proc

32、_file(); if(0 err) printk(KERN_ALERTproc file create failed.n); goto PROC_FILE_CREATE_ERR; return 0; PROC_FILE_CREATE_ERR: snsled_delete_devfiles(devt);DEVFILES_CREATE_ERR: snsled_unsetup_dev(g_snsled_ptr);DEVICE_SETUP_ERR: kfree(g_snsled_ptr); ALLOC_MAJOR_ERR: snsled_release_major();KMALLOC_ERR: re

33、turn err;static void snsled_exit(void) dev_t devt = MKDEV(g_snsled_major, g_snsled_minor); snsled_delete_proc_file(); snsled_delete_devfiles(devt); snsled_unsetup_dev(g_snsled_ptr); kfree(g_snsled_ptr); snsled_release_major();module_init(snsled_init);module_exit(snsled_exit);二、配置Kconfig在snsled目錄中,新建

34、Kconfig文件:config SNSLED tristate snsled Driver default n #y ? help This is the sns led driver.其中,tristate表示編譯選項(xiàng)HELLO支持在編譯內(nèi)核時(shí),hello模塊支持以模塊、內(nèi)建和不編譯三種編譯方法。三、配置Makefile1、在snsled目錄中,新建snsled文件夾對(duì)應(yīng)的Makefile:#obj-$(CONFIG_SNSLED) += snsled.oobj-y += snsled.o上面根據(jù) CONFIG_SNSLED的值確定是否編譯,y為編譯。2、修改snsled的父目錄 driv

35、ers/下的Makefile,加入:obj-$(CONFIG_HELLO) += snsled/這樣便能在編譯時(shí)編譯到snsled這個(gè)文件夾。四、配置系統(tǒng)的autoconfig打開 mediatek/config/bbk73_gb/autoconfig/kconfig/project,加入:CONFIG_SNSLED=y在這里定義變量 CONFIG_SNSLED.ps:目前這里配置好像還不能snsled自動(dòng)編譯進(jìn)去,目前的操作是直接在用到CONFIG_SNSLED的地方用y替代。五、編譯./makeMtk bbk73_gb remake kernel bootimage編寫hal模塊1新建xx

36、x.h文件進(jìn)入hardware/libhardware/include/hardware目錄,新建vircdev.h文件:#ifndef ANDROID_HELLO_INTERFACE_H#define ANDROID_HELLO_INTERFACE_H#include _BEGIN_DECLS/*定義模塊ID*/#define HELLO_HARDWARE_MODULE_ID hello/*硬件模塊結(jié)構(gòu)體*/struct hello_module_t struct hw_module_t common;/*硬件接口結(jié)構(gòu)體*/struct hello_device_t struct hw_de

37、vice_t common;int fd;int (*set_val)(struct hello_device_t* dev, int val);int (*get_val)(struct hello_device_t* dev, int* val);_END_DECLS#endif這里按照Android硬件抽象層規(guī)范的要求,分別定義模塊ID、模塊結(jié)構(gòu)體hello_module_t以及硬件接口結(jié)構(gòu)體hello_device_t。在硬件接口結(jié)構(gòu)體中,fd表示設(shè)備文件描述符,對(duì)應(yīng)linux下我們經(jīng)常接觸到的設(shè)備文件/dev/xxx,set_val和get_val為該HAL對(duì)上提供的函數(shù)接口。2新建

38、xxx.c文件進(jìn)入到hardware/libhardware/modules目錄,新建hello目錄,并添加hello.c文件。 hello.c的內(nèi)容較多,我們分段來看。1包含相關(guān)頭文件和定義相關(guān)結(jié)構(gòu)#define LOG_TAG HelloStub#include #include #include #include #include #include #define DEVICE_NAME /dev/hello#define MODULE_NAME Hello#define MODULE_AUTHOR shyluo/*設(shè)備打開和關(guān)閉接口*/static int hello_device_o

39、pen(const struct hw_module_t* module, const char* name, struct hw_device_t* device);static int hello_device_close(struct hw_device_t* device);/*設(shè)備訪問接口*/static int hello_set_val(struct hello_device_t* dev, int val);static int hello_get_val(struct hello_device_t* dev, int* val);/*模塊方法表*/static struct

40、hw_module_methods_t hello_module_methods = open: hello_device_open;/*模塊實(shí)例變量*/struct hello_module_t HAL_MODULE_INFO_SYM = common: tag: HARDWARE_MODULE_TAG,version_major: 1,version_minor: 0,id: HELLO_HARDWARE_MODULE_ID,name: MODULE_NAME,author: MODULE_AUTHOR,methods: &hello_module_methods,這里,實(shí)例變量名必須為H

41、AL_MODULE_INFO_SYM,tag也必須為HARDWARE_MODULE_TAG,這是Android硬件抽象層規(guī)范規(guī)定的。2定義hello_device_open函數(shù)static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t* device) struct hello_device_t* dev;dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t);if(!dev)

42、LOGE(Hello Stub: failed to alloc space);return -EFAULT;memset(dev, 0, sizeof(struct hello_device_t);dev-common.tag = HARDWARE_DEVICE_TAG;dev-common.version = 0;dev-common.module = (hw_module_t*)module;dev-common.close = hello_device_close;dev-set_val = hello_set_val;dev-get_val = hello_get_val;if(de

43、v-fd = open(DEVICE_NAME, O_RDWR) = -1) LOGE(Hello Stub: failed to open /dev/hello - %s., strerror(errno);free(dev);return -EFAULT;*device = &(dev-common);LOGI(Hello Stub: open /dev/hello successfully.);return 0;DEVICE_NAME定義為/dev/hello。由于設(shè)備文件是在內(nèi)核驅(qū)動(dòng)里面通過device_create創(chuàng)建的,而device_create創(chuàng)建的設(shè)備文件默認(rèn)只有root用戶

44、可讀寫,而hello_device_open一般是由上層APP來調(diào)用的,這些APP一般不具有root權(quán)限,這時(shí)候就導(dǎo)致打開設(shè)備文件失?。篐ello Stub: failed to open /dev/hello - Permission denied.解決辦法是類似于Linux的udev規(guī)則,打開Android源代碼工程目錄下,進(jìn)入到system/core/rootdir目錄,里面有一個(gè)名為ueventd.rc文件,往里面添加一行:/dev/hello 0666 root root3定義自定義的api函數(shù)這里定義hello_device_close、hello_set_val和hello_get_val這三個(gè)函數(shù):static int hello_device_close(struct hw_device_t* device) struct hello_device_t* hello_device = (struct hello_device_t*)device;if(hello_device) close(hello_device-fd);free(hello_device);return 0;static int hello_

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論