织梦CMS - 轻松建站从此开始!

罗索

当前位置: 主页>嵌入式开发>Android>

OK6410a的Android HAL层代码编写笔记

落鹤生 发布于 2014-03-12 23:33 点击:次 
编写LED灯的Linux驱动程序代码 之所以使用存在HAL层,是为了保护对硬件驱动过程的逻辑与原理; 所以,残留在Linux驱动层的代码,只保留了基本的读写操作,而不含有关键的逻辑思维;本文大部分代码摘取自某本书的源程序代码。
TAG: HAL  驱动  

一、编写LED灯的Linux驱动程序代码

  之所以使用存在HAL层,是为了保护对硬件驱动过程的逻辑与原理;

  所以,残留在Linux驱动层的代码,只保留了基本的读写操作,而不含有关键的逻辑思维;

  1. leds_hal_define.h (包含对读写寄存器的宏定义)

  1. #define S3C6410_LEDS_HAL_WRITE_GPMPUD 1 
  2. #define S3C6410_LEDS_HAL_WRITE_GPMCON 2 
  3. #define S3C6410_LEDS_HAL_WRITE_GPMDAT 3 
  4. #define S3C6410_LEDS_HAL_READ_GPMPUD 4 
  5. #define S3C6410_LEDS_HAL_READ_GPMCON 5 
  6. #define S3C6410_LEDS_HAL_READ_GPMDAT 6 

2. s3c6410_leds_hal.h (包含必须的头文件及设备的定义)

  1. #include <linux/fs.h> 
  2. #include <linux/cdev.h> 
  3. #include <linux/pci.h>  
  4. #include <linux/uaccess.h>  
  5. #include <mach/map.h>  
  6. #include <mach/regs-gpio.h> 
  7. #include <mach/gpio-bank-m.h> 
  8.  
  9. #define DEVICE_NAME "s3c6410_leds_hal" 
  10. #define DEVICE_COUNT 1 
  11. #define S3C6410_LEDS_MAJOR 0 
  12. #define S3C6410_LEDS_MINOR 234 

3. s3c6410_leds_hal.c (包含对设备文件读写操作)

  1. #include "s3c6410_leds_hal.h" 
  2. #include "leds_hal_define.h" 
  3.  
  4. static unsigned char mem[5];/* 第1字节保存寄存器类型,后边4字节保存寄存器的值 */ 
  5. static int major = S3C6410_LEDS_MAJOR; 
  6. static int minor = S3C6410_LEDS_MINOR; 
  7. static dev_t dev_number; 
  8. static struct class *leds_class = NULL; 
  9.  
  10. //字节转换int类型 
  11. static int bytes_to_int(unsigned char buf[], int start){ 
  12.     int n=0; 
  13.     n = ((int)buf[start]<<24 
  14.             | (int)buf[start+1]<<16 
  15.             | (int)buf[start+2]<<8 
  16.             |(int)buf[start+3]); 
  17.     return n; 
  18.  
  19. //将int转换成bytes 
  20. static void int_to_bytes(int n, unsigned char buf[], int start){ 
  21.     buf[start] = n >> 24; 
  22.     buf[start+1] = n >> 16; 
  23.     buf[start+2] = n >> 8; 
  24.     buf[start+3] = n; 
  25.  
  26. //设备的写操作 
  27. static ssize_t s3c6410_leds_hal_write(struct file *file
  28. const char __user *buf, size_t count, loff_t *ppos){ 
  29.     if (copy_from_user(mem, buf, 5)){ 
  30.         return -EFAULT; 
  31.     } 
  32.     else
  33.         int gpm_type = mem[0]; 
  34.         switch ( gpm_type ) { 
  35.             case S3C6410_LEDS_HAL_WRITE_GPMCON: 
  36.                 iowrite32(bytes_to_int(mem,1),S3C64XX_GPMCON); 
  37.                 break
  38.  
  39.             case S3C6410_LEDS_HAL_WRITE_GPMPUD: 
  40.                 iowrite32(bytes_to_int(mem,1),S3C64XX_GPMPUD); 
  41.                 break
  42.  
  43.             case S3C6410_LEDS_HAL_WRITE_GPMDAT: 
  44.                 iowrite32(bytes_to_int(mem,1),S3C64XX_GPMDAT); 
  45.                 break
  46.  
  47.             default:     
  48.                 printk(DEVICE_NAME "\tnot the write type.\n"); 
  49.                 break
  50.         } 
  51.     } 
  52.     return 5; 
  53.  
  54. //设备的读操作 
  55. static ssize_t s3c6410_leds_hal_read(struct file *file
  56. char __user *buf, size_t count, loff_t *ppos){ 
  57.     int gpm_type = mem[0]; 
  58.     int gpm_value = 0; 
  59.     switch ( gpm_type ) { 
  60.             case S3C6410_LEDS_HAL_READ_GPMCON: 
  61.                 gpm_value=ioread32(S3C64XX_GPMCON); 
  62.                 break
  63.  
  64.             case S3C6410_LEDS_HAL_READ_GPMPUD: 
  65.                 gpm_value=ioread32(S3C64XX_GPMPUD); 
  66.                 break
  67.  
  68.             case S3C6410_LEDS_HAL_READ_GPMDAT: 
  69.                 gpm_value=ioread32(S3C64XX_GPMDAT); 
  70.                 break
  71.  
  72.             default:     
  73.                 printk(DEVICE_NAME "\tnot the read type.\n"); 
  74.                 break
  75.     } 
  76.     int_to_bytes(gpm_value, mem, 1);            /* 转换成byte数组 */ 
  77.     if (copy_to_user(buf, (void*)mem, 5)){      /* 把数据复制到用户空间 */ 
  78.         return -EFAULT; 
  79.     } 
  80.     return 5;                                   /* 返回已读数据长度 */ 
  81.  
  82. static struct file_operations dev_fops= 
  83.     .owner = THIS_MODULE, 
  84.     .read = s3c6410_leds_hal_read, 
  85.     .write = s3c6410_leds_hal_write 
  86. }; 
  87.  
  88. static struct cdev leds_cdev; 
  89.  
  90. //创建设备文件 
  91. static int leds_create_device(void){ 
  92.     int ret = 0; 
  93.     int err = 0; 
  94.  
  95.     cdev_init(&leds_cdev, &dev_fops);           /* 初始化cdev成员,与dev_fops连接 */ 
  96.     leds_cdev.owner = THIS_MODULE; 
  97.     if (major>0){                               /* 若大于0,选择手动分配 */ 
  98.         dev_number = MKDEV(major, minor); 
  99.         err = register_chrdev_region(dev_number, DEVICE_COUNT,DEVICE_NAME); 
  100.         if (err<0){ 
  101.             printk(KERN_WARNING "register_chrdev_region() failed\n"); 
  102.             return err; 
  103.         } 
  104.     } 
  105.     else {                                      /* 若主设备号小等于0,使用自动分配设备号 */ 
  106.         err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT,DEVICE_NAME); 
  107.         if (err<0){ 
  108.             printk(KERN_WARNING "alloc_chrdev_region() failed\n"); 
  109.             return err; 
  110.         } 
  111.         major = MAJOR(leds_cdev.dev);           /* 及时保存主设备号 */ 
  112.         minor = MINOR(leds_cdev.dev);           /* 及时保存次设备号*/ 
  113.         dev_number = leds_cdev.dev;             /* 保存设备号信息*/ 
  114.     } 
  115.     ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT); /* 添加驱动设备 */ 
  116.     leds_class = class_create(THIS_MODULE, DEVICE_NAME); /* 创建类型*/ 
  117.     device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME); /* 创建设备 */ 
  118.     return ret; 
  119.  
  120. //驱动初始化函数 
  121. static int __init leds_init(void){ 
  122.     int ret; 
  123.     ret = leds_create_device(); 
  124.     printk(DEVICE_NAME "\tintialized\n"); 
  125.     return ret; 
  126.  
  127. //驱动卸载函数 
  128. static void __exit leds_destroy_device(void){ 
  129.     device_destroy(leds_class, dev_number); 
  130.     if (leds_class){ 
  131.         class_destroy(leds_class); 
  132.     } 
  133.     unregister_chrdev_region(dev_number, DEVICE_COUNT); 
  134.     return
  135.  
  136. module_init(leds_create_device); 
  137. module_exit(leds_destroy_device); 
  138. MODULE_AUTHOR("linkscue"); 
  139. MODULE_DESCRIPTION("leds driver witten via hal"); 
  140. MODULE_ALIAS("leds driver hal"); 
  141. MODULE_LICENSE("GPL"); 

4. Makefile

  1. obj-m := s3c6410_leds_hal.o 
  2. PWD := $(shell pwd) 
  3. #CROSS_COMPILE ?= arm-none-linux-gnueabi- 
  4. #CC := $(CROSS_COMPILE)gcc 
  5. #CFLAGS += -static 
  6. KPATH := /media/Source/Forlinx/android2.3_kernel_v1.01 
  7. all: 
  8.     make -C $(KPATH) M=$(PWD) modules 
  9. clean: 
  10.     rm -rf *.o *.ko *.mod.c Module.* modules.* 

在编写好了Linux驱动程序代码之后,把make生成的s3c6410_leds_hal.ko上传至OK6410a并使用insmod安装,继续下一步。

二、编写LED灯的Android HAL层代码

  这一层使用的协议并不是GPL,不被强制地开放源代码,这一层,包含了对LED控制过程中的所有的逻辑思维;

  在本例子当中,这LED灯的初始化寄存器操作的逻辑,打开或者关闭LED灯时应当向寄存器写入什么数据等等。

  1. leds_hal.h (包含必须的头文件及宏定义)

  1. #include <hardware/hardware.h> 
  2. #include <fcntl.h> 
  3. #include <cutils/log.h> 
  4.  
  5. struct led_module_t{ 
  6.     struct hw_module_t hw_module; 
  7. }; 
  8.  
  9. struct led_control_device_t{ 
  10.     struct hw_device_t hw_device; 
  11.     int (*set_on)(struct led_control_device_t *dev, int32_t led); 
  12.     int (*set_off)(struct led_control_device_t *dev, int32_t led); 
  13. }; 
  14.  
  15. #define LED_HARDWARE_MODULE_ID "led_hal" 
  16.  
  17.  
  18. /*----------------------------------------- 
  19.  *  编写HAL模块需要的3个非常重要的结构体: 
  20.  *      hw_module_t  
  21.  *      hw_device_t 
  22.  *      hw_module_methods_t 
  23.  *  位置:hardware/libhardware/include/hardware/hardware.h 
  24.  *---------------------------------------*/ 

2. leds_hal.c (包含对灯控制的所有逻辑思想与操作)

  1. #include "leds_hal.h" 
  2. #include "leds_hal_define.h" 
  3.  
  4. int dev_file = 0; 
  5.  
  6. /*----------------------------------------- 
  7.  *  控制LED开关的通用函数 
  8.  *  led表示灯的序号,从0开始 
  9.  *  on_off表示开(1)、关(0) 
  10.  *-----------------------------------------*/ 
  11. int led_on_off(struct led_control_device_t *dev, int32_t led, int32_t on_off){ 
  12.     if (led>0 && led<3){ 
  13.         if (on_off == 1){ 
  14.             LOGI("LED stub: set %d on", led); 
  15.         } 
  16.         else { 
  17.             LOGI("LED stub: set %d off", led); 
  18.         } 
  19.         unsigned char buf[5]; 
  20.         buf[0] = S3C6410_LEDS_HAL_READ_GPMDAT;  /* 准备要读取 */ 
  21.         write(dev_file, buf, 5); 
  22.         read(dev_file, buf, 5); 
  23.         buf[0] = S3C6410_LEDS_HAL_WRITE_GPMDAT; /* 准备要写入 */ 
  24.  
  25.         switch ( led ) { 
  26.             case 0:     
  27.                 if (on_off == 1){ 
  28.                     buf[4]&=0xFE;/* 1111,1110,GPMDAT最后一位是0 */ 
  29.                 } 
  30.                 else if (on_off == 0){ 
  31.                     buf[4]|=0x1; /* 0000,0001,GPMDAT最后一位是1 */ 
  32.                 } 
  33.                 break
  34.  
  35.             case 2:     
  36.                 if (on_off == 1){ 
  37.                     buf[4]&=0xFD;               /* 1111,1101 */ 
  38.                 } 
  39.                 else if (on_off == 0){ 
  40.                     buf[4]|=0x2;                /* 0000,0010 */ 
  41.                 } 
  42.                 break
  43.  
  44.             case 3:     
  45.                 if (on_off == 1){ 
  46.                     buf[4]&=0xFB;               /* 1111,1011 */ 
  47.                 } 
  48.                 else if (on_off == 0){ 
  49.                     buf[4]|=0x4;                /* 0000,0100 */ 
  50.                 } 
  51.                 break
  52.  
  53.             case 4:     
  54.                 if (on_off == 1){ 
  55.                     buf[4]&=0xF7;               /* 1111,0111 */ 
  56.                 } 
  57.                 else if (on_off == 0){ 
  58.                     buf[4]|=0x8;                /* 0000,1000 */ 
  59.                 } 
  60.                 break
  61.  
  62.             default:     
  63.                 break
  64.         } 
  65.         write(dev_file, buf, 5); 
  66.     } 
  67.     else { 
  68.         LOGI("LED Stub: set led %d on error,no this led", led); 
  69.     } 
  70.     return 0; 
  71.  
  72. /*---------------------------------------- 
  73.  *  打开指定的LED灯 
  74.  *--------------------------------------*/ 
  75. int led_on(struct led_control_device_t *dev, int32_t led){ 
  76.     return led_on_off(dev, led, 1); 
  77.  
  78. /*--------------------------------------- 
  79.  *  关闭指定的LED灯 
  80.  *-------------------------------------*/ 
  81. int led_off(struct led_control_device_t *dev, int32_t led){ 
  82.     return led_on_off(dev, led, 0); 
  83.  
  84. /*------------------------------------------ 
  85.  *  关闭设备函数,HAL模块的事件函数之一 
  86.  *---------------------------------------*/ 
  87. int  led_device_close(struct hw_device_t *device){ 
  88.     //强行转换成 led_control_device_t 
  89.     struct led_control_device_t *ctx = (struct led_control_device_t*)device; 
  90.     if (ctx){ 
  91.         free(ctx);                              /* 释放设备 */ 
  92.     } 
  93.     close(dev_file); 
  94.     return 0; 
  95.  
  96.  
  97. /*------------------------------------------- 
  98.  *  初始化GPMCON,GPMPUD寄存器 
  99.  *------------------------------------*/ 
  100. static void leds_init_gpm(){ 
  101.     int tmp = 0; 
  102.     unsigned char buf[5]; 
  103.  
  104.     //初始化寄存器GPMDAT 
  105.     buf[0] = S3C6410_LEDS_HAL_READ_GPMCON; 
  106.     write(dev_file, buf, 5); 
  107.     read(dev_file, buf, 5); 
  108.     buf[3] |= 0x11;                             /* 0001,0001 */ 
  109.     buf[4] |= 0x11;                             /* 0001,0001 */ 
  110.     buf[0] = S3C6410_LEDS_HAL_WRITE_GPMCON; 
  111.     write(dev_file, buf, 5); 
  112.  
  113.     //初始化寄存器GPMPUD 
  114.     buf[0] = S3C6410_LEDS_HAL_READ_GPMPUD; 
  115.     write(dev_file, buf, 5); 
  116.     read(dev_file, buf, 5); 
  117.     buf[4] |= 0xAA; 
  118.     buf[0] = S3C6410_LEDS_HAL_WRITE_GPMPUD; 
  119.     write(dev_file, buf, 5); 
  120.  
  121.  
  122. /*------------------------------------ 
  123.  *  打开设备的函数 
  124.  *---------------------------*/ 
  125. static int led_device_open(const struct hw_module_t *module, const char *name, 
  126.         struct hw_device_t **device){ 
  127.     struct led_control_device_t *dev; 
  128.     dev = (struct led_control_device_t *)malloc(sizeof(*dev)); 
  129.     memset(dev, 0, sizeof(*dev));               /* 清理内存空间 */ 
  130.     dev->hw_device.tag = HARDWARE_DEVICE_TAG;   /* HAL设备的标志 */ 
  131.     dev->hw_device.version = 0;                 /* HAL设备的版本号 */ 
  132.     dev->hw_device.module = (struct hw_module_t *)module;
  133.  /* HAL模块的hw_module_t结构体 */ 
  134.     dev->hw_device.close = led_device_close;    /* 关闭设备的函数 */ 
  135.     dev->set_on = led_on;                       /* HAL的接口函数 */ 
  136.     dev->set_off = led_off;                     /* HAL的接口函数 */ 
  137.     *device = (hw_device_t *)dev;               /* 可替换为*device = &dev->hw_device */ 
  138.     dev_file = open("/dev/s3c6410_leds_hal", O_RDWR); 
  139.     if (dev_file < 0){ 
  140.         LOGI("LED Stub: open /dev/s3c6410_leds_hal  fail."); 
  141.     } 
  142.     else { 
  143.         LOGI("LED Stub: open /dev/s3c6410_leds_hal success ."); 
  144.     } 
  145.     leds_init_gpm;                              /* 初始化寄存器 */ 
  146.     return 0; 
  147.  
  148. /*----------------------------------- 
  149.  *  初始化hw_module_method_t结构体的open成员变量 
  150.  *---------------------------------*/ 
  151. static struct hw_module_methods_t led_module_methods = { 
  152.     open: led_device_open 
  153. }; 
  154.  
  155. /*---------------------------------- 
  156.  *  初始化描述HAL模块信息的结构体,此结构体变量名必须是HAL_MODULE_INFO_SYM 
  157.  *----------------------------*/ 
  158. struct led_module_t HAL_MODULE_INFO_SYM = { 
  159.     hw_module: 
  160.     { 
  161.         tag:HARDWARE_MODULE_TAG,                /* 初始化模块标志 */ 
  162.         version_major:1,                        /* 模块的主版本号 */ 
  163.         version_minor:0,                        /* 模块的次版本情 */ 
  164.         id:LED_HARDWARE_MODULE_ID,              /* 初始化模块的ID,通过ID找到此模块 */ 
  165.         name:"Sample LED HAL Stub",             /* 初始化模块的名称 */ 
  166.         author:"linkscue",                      /* 初始化模块的作者 */ 
  167.         methods:&led_module_methods,            /* 初始化模块的open函数指针 */ 
  168.     } 
  169. }; 

3. Android.mk

在Android源代码目录下,创建一个 hardware/leds_hal(名字和路径可以随意,当然也可以放在device目录上对应的设备上);

  把源代码 Android.mk  leds_hal.c  leds_hal_define.h  leds_hal.h 复制至 hardware/leds_hal 目录下(可通过ln -s链接);

  在配置好编译环境之后,通过 mmm hardware/leds_hal 生成HAL共享库文件 led_hal.default.so(命名与头文件的ID有关);

三、编写调用HAL模块的Service

  此模块中一个非常重要的函数是 hw_get_module ,它通过在leds_hal.h中定义的LED_HARDWARE_MODULE_ID找到LED的HAL模块,并取得led_module_t结构体。通过 led_module_t.hw_module.methods.open 函数初始化LED驱动,并通过 open 函数返回 led_control_device_t 结构体,在此结构体中含有我们需要的对LED操作的set_on和set_off函数指针。这一段由于使用了C++和JNI(NDK)编程,阅读起来相对有点晦涩难懂,不过编程量相对也比较少,只需要两文件即可。

  1. LedHalService.cpp (主要的源代码文件)

  1. #include <stdlib.h> 
  2. #include <stdio.h> 
  3. #include <string.h> 
  4. #include <unistd.h> 
  5. #include <assert.h>  
  6. #include <jni.h> 
  7. #include <leds_hal.h> 
  8.  
  9. struct led_control_device_t *led_hal_device = NULL; 
  10.  
  11. /*--------------------------------- 
  12.  *  JNI函数,打开指定的LED 
  13.  *----------------------------*/ 
  14. static jboolean led_setOn(JNIEnv *env, jobject thiz, jint led){ 
  15.     LOGI("Led HAL JNI: led_setOn() is invoked."); 
  16.     if (led_hal_device == NULL){ 
  17.         LOGI("LED HAL JNI: led_hal_device was not fetched correcttly."); 
  18.         return -1; 
  19.     } 
  20.     else { 
  21.         return led_hal_device->set_on(led_hal_device, led); 
  22.     } 
  23.  
  24. /*------------------------------------ 
  25.  *  JNI函数,关闭指定的LED 
  26.  *----------------------------------*/ 
  27. static jboolean led_setOff(JNIEnv *env, jobject thiz, jint led){ 
  28.     LOGI("Led HAL JNI: led_setOff() is invoked."); 
  29.     if (led_hal_device == NULL){ 
  30.         LOGI("LED HAL JNI: led_hal_device was not fetched correcttly."); 
  31.         return -1; 
  32.     } 
  33.     else { 
  34.         return led_hal_device->set_off(led_hal_device, led); 
  35.     } 
  36.  
  37. static inline int led_control_open(const struct hw_module_t *module,  
  38.         struct led_control_device_t **device){ 
  39.     /* 
  40.      * 调用led_module_t.hw_module.methods.open进行一系列的初始化工作 
  41.      * open函数会获取led_control_device_t结构体 
  42.      */ 
  43.     return module->methods->open(module, LED_HARDWARE_MODULE_ID,  
  44.             (struct hw_device_t**) device); 
  45.  
  46. //JNI函数,此方法通过LED_HARDWARE_MODULE_ID找到HAL模块 
  47. static jboolean led_init(JNIEnv *env, jclass clazz){ 
  48.     led_module_t *module;  
  49.     LOGE("************start find hal************"); 
  50.     LOGE("LED_HARDWARE_MODULE_ID"); 
  51.     if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t **) &module) == 0){ 
  52.         LOGI("LedService JNI: LED Stub found."); 
  53.         if (led_control_open(&module->hw_module, &led_hal_device) == 0){ 
  54.             LOGI("LedService JNI: Got LED operations."); 
  55.             return 0; 
  56.         } 
  57.     } 
  58.     LOGE("LedService JNI: Got LED operations failed."); 
  59.     return -1; 
  60.  
  61. //定义JNI函数的映射 
  62. static const JNINativeMethod methods[] = { 
  63.     { "_init""()Z", (void*) led_init }, 
  64.     { "_seton""(I)Z" ,(void *) led_setOn }, 
  65.     { "_setoff""(I)Z", (void *) led_setOff }, 
  66. }; 
  67.  
  68. /*---------------------------------- 
  69.  * Java数据类型在JNI中的描述符: 
  70.  *  boolean                 Z 
  71.  *  byte                    B 
  72.  *  char                    C 
  73.  *  short                   S 
  74.  *  int                     I 
  75.  *  long                    J 
  76.  *  float                   F 
  77.  *  double                  D 
  78.  *------------------------------*/ 
  79.  
  80. /*------------------------------- 
  81.  *  Java复杂类型在JNI的描述符: 
  82.  *  String                  "Ljava/lang/String;" 
  83.  *  int[]                   "[I" 
  84.  *  Object[]                "[Ljava/lang/Object;" 
  85.  *  小技巧: 
  86.  *      [   表示数组,比如byte[]在JNI中是"[B" 
  87.  *      V   表示未返回任何值即void,比如void method(int a)的返回值是"(I)V" 
  88.  *------------------------------*/ 
  89.  
  90. //将JNI程序库与Java类绑定 
  91. int register_led_hal_jni(JNIEnv *env){ 
  92.     //必须由此类调用当前的JNI程序库 
  93.     static const char *const kClassName = "mobile/android/leds/hal/service/LedHalService"
  94.     jclass clazz; 
  95.     clazz = env->FindClass(kClassName);         /* 获取LedHalService类的jclass对象 */ 
  96.     if (clazz == NULL){ 
  97.         LOGE("Can't find class %s", kClassName); 
  98.         return -1; 
  99.     } 
  100.  
  101.     /* 
  102.      * 将此函数注册至LedHalService类当中的一个方法 
  103.      * sizeof(methods) / sizeof(methods[0]) 用于计算methods的长度 
  104.      */ 
  105.     if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]))
  106.  != JNI_OK){ 
  107.         LOGE("Failed register methods for %s \n", kClassName); 
  108.         return -1; 
  109.     } 
  110.     return 0; 
  111.  
  112. //自动调用JNI_OnLoad函数,用于初始化JNI模块 
  113. jint JNI_OnLoad(JavaVM *vm, void *reserved){ 
  114.     JNIEnv *env = NULL; 
  115.     jint result = -1; 
  116.     /* 
  117.      * JNI_VERSION_1_4表明只能在JSE1.4版本以上才能使用 
  118.      */ 
  119.     if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){ 
  120.         LOGE("GetEnv failed!"); 
  121.         return result; 
  122.     } 
  123.     register_led_hal_jni(env); 
  124.     return JNI_VERSION_1_4; 

2. Android.mk

  1. #Android.mk 
  2. LOCAL_PATH := $(call my-dir) 
  3. include $(CLEAR_VARS) 
  4. LOCAL_MODULE_TAGS := eng 
  5. LOCAL_MODULE := led_hal_jni 
  6.  
  7. #指定Service程序库的存放路径(指编译出来的.so存放的地方) 
  8. LOCAL_MODULE_PATH := /home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni 
  9. LOCAL_SRC_FILES := \ 
  10.     LedHalService.cpp 
  11.  
  12. #指定共享库的位置 
  13. LOCAL_SHARED_LIBRARIES := \ 
  14.     libandroid_runtime \ 
  15.     libcutils \ 
  16.     libhardware \ 
  17.     libhardware_legacy \ 
  18.     libnativehelper \ 
  19.     libsystem_server \ 
  20.     libutils \ 
  21.     libui \ 
  22.     libsurfaceflinger_client 
  23.         
  24. #指定头文件的位置 
  25. LOCAL_C_INCLUDES += \ 
  26.     $(JNI_H_INCLUDE) \ 
  27.     hardware/leds_hal 
  28.  
  29. #指定预链接模式 
  30. LOCAL_PRELINK_MODULE := false 
  31.  
  32. include $(BUILD_SHARED_LIBRARY) 

Android.mk  LedHalService.cpp放至同一目录(/home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni);

  配置好Android编译环境之后,使用命令 mmm -B /home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni 编译;

    mmm  表示编译指定目录的中的内容

    -B    表示强制编译其中的内容(即使源代码.cpp文件没有任何改变)

  小技巧:

    可以不用把/home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni移至Android源代码目录下亦可编译

 

(未完待续)..

注:本文大部分代码摘取自某本书的源程序代码。

(scue)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201403/16929.html]
本文出处:博客园 作者:scue
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容