conlan
论坛版主
论坛版主
阅读:12778回复:8

简单的JNI例子

楼主#
更多 发布于:2019-07-29 16:43
客户要求做一个可以调节RGB颜色的LED灯。这个从界面上来比较简单,做3个SeekBar,分别控制R,G,B就好了。
xml如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/lamp_sceen_xsjbg"
    android:orientation="vertical" >


    <View
        android:layout_width="match_parent"
        android:layout_height="100dp" />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:gravity="center"
        android:orientation="vertical" >


        <LinearLayout
            android:layout_width="1000dp"
            android:layout_height="80dp"
            android:gravity="center"
            android:orientation="horizontal" >


            <Button
                android:id="@+id/lamp_red"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:background="@drawable/left_bg"
                android:text="@string/color_red"
                android:textColor="#FFFFFFFF"
                android:textSize="36px" />


            <View
                android:layout_width="100dp"
                android:layout_height="80dp" />


            <Button
                android:id="@+id/lamp_red_left"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:background="@drawable/reduction" />


            <View
                android:layout_width="10dp"
                android:layout_height="80dp" />


            <SeekBar
                android:id="@+id/lamp_red_seekBar"
                android:layout_width="450dp"
                android:layout_height="wrap_content"
                android:paddingEnd="0dp"
                android:paddingLeft="30px"
                android:paddingRight="30px"
                android:paddingStart="0dp"
                android:progressDrawable="@drawable/progress_bg"
                android:thumb="@drawable/line_location" />


            <View
                android:layout_width="10dp"
                android:layout_height="80dp" />


            <Button
                android:id="@+id/lamp_red_right"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:background="@drawable/add" />
        </LinearLayout>        
     <View
                android:layout_width="match_parent"
                android:layout_height="20dp" />
 
 <LinearLayout
            android:layout_width="1000dp"
            android:layout_height="80dp"
            android:gravity="center"
            android:orientation="horizontal" >


            <Button
                android:id="@+id/lamp_green"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:background="@drawable/left_bg"
                android:text="@string/color_green"
                android:textColor="#FFFFFFFF"
                android:textSize="36px" />


            <View
                android:layout_width="100dp"
                android:layout_height="80dp" />


           <Button
                android:id="@+id/lamp_green_left"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:background="@drawable/reduction" />


            <View
                android:layout_width="10dp"
                android:layout_height="80dp" />


            <SeekBar
                android:id="@+id/lamp_green_seekBar"
                android:layout_width="450dp"
                android:layout_height="wrap_content"
                android:paddingEnd="0dp"
                android:paddingLeft="30px"
                android:paddingRight="30px"
                android:paddingStart="0dp"
                android:progressDrawable="@drawable/progress_bg"
                android:thumb="@drawable/line_location" />


            <View
                android:layout_width="10dp"
                android:layout_height="80dp" />


            <Button
                android:id="@+id/lamp_green_right"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:background="@drawable/add" />
        </LinearLayout>
 
 <View
                android:layout_width="match_parent"
                android:layout_height="20dp" />
 
 <LinearLayout
            android:layout_width="1000dp"
            android:layout_height="80dp"
            android:gravity="center"
            android:orientation="horizontal" >


            <Button
                android:id="@+id/lamp_blue"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:background="@drawable/left_bg"
                android:text="@string/color_blue"
                android:textColor="#FFFFFFFF"
                android:textSize="36px" />


            <View
                android:layout_width="100dp"
                android:layout_height="80dp" />


           <Button
                android:id="@+id/lamp_blue_left"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:background="@drawable/reduction" />


            <View
                android:layout_width="10dp"
                android:layout_height="80dp" />


            <SeekBar
                android:id="@+id/lamp_blue_seekBar"
                android:layout_width="450dp"
                android:layout_height="wrap_content"
                android:paddingEnd="0dp"
                android:paddingLeft="30px"
                android:paddingRight="30px"
                android:paddingStart="0dp"
                android:progressDrawable="@drawable/progress_bg"
                android:thumb="@drawable/line_location" />


            <View
                android:layout_width="10dp"
                android:layout_height="80dp" />


            <Button
                android:id="@+id/lamp_blue_right"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:background="@drawable/add" />
        </LinearLayout>
 
        
    </LinearLayout>


</LinearLayout>

activity里面比较简单,我就不copy了。
然后activity需要加载驱动:
static {
if("i2cmode".equals(isLampModel)){
System.loadLibrary("lampctrl");
}
    }


    public native int lampctrl(int rgb);

lampctrl是调用JNI的。JNI代码如下:
#define AUDIOOUT_IOC_MAGIC 'T'
#define LAMP_CHOOSE_RGB     _IOW(AUDIOOUT_IOC_MAGIC, 0x09, int)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)


static const char *classPathName = "com/android/settings/LampActivity";

static int fd = -1;


static jint LampActivity_lampctrl(JNIEnv* env, jobject thiz, jint rgb){
        int tmp = -1;

if(fd < 0){
fd = open("/dev/aswitch", O_RDWR|O_NONBLOCK, 0);
}
if(fd < 0)
{
printf("open audiosw drivers failed");
return -1;
}

        LOGE("!!!!!!!rgb = 0x%x\n", rgb);
        tmp = rgb;
        if(-1 == ioctl(fd, LAMP_CHOOSE_RGB, &tmp)){
                return -1;
        }
        return 0;
}


static JNINativeMethod methods[] = {
    {"lampctrl", "(I)I",(void*)LampActivity_lampctrl},
};

/*
 * Register several native methods for one class.
 */
static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;

    clazz = env->FindClass(className);
    if (clazz == NULL) {
        ALOGE("Native registration unable to find class '%s'", className);
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        ALOGE("RegisterNatives failed for '%s'", className);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/*
 * Register native methods for all classes we know about.
 *
 * returns JNI_TRUE on success.
 */
static int registerNatives(JNIEnv* env)
{
  if (!registerNativeMethods(env, classPathName,
                 methods, sizeof(methods) / sizeof(methods[0]))) {
    return JNI_FALSE;
  }

  return JNI_TRUE;
}


// ----------------------------------------------------------------------------

/*
 * This is called by the VM when the shared library is first loaded.
 */
 
typedef union {
    JNIEnv* env;
    void* venv;
} UnionJNIEnvToVoid;

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    jint result = -1;
    JNIEnv* env = NULL;
    
    ALOGI("JNI_OnLoad");

    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("ERROR: GetEnv failed");
        goto bail;
    }
    env = uenv.env;

    if (registerNatives(env) != JNI_TRUE) {
        ALOGE("ERROR: registerNatives failed");
        goto bail;
    }
    
    result = JNI_VERSION_1_4;
    
bail:
    return result;
}

然后通过ioctrl调用底层驱动,驱动如下:
/* Copyright (C) 2010 ROCKCHIP, Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

//#define DEBUG


#include <linux/types.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/unistd.h>
#include <linux/delay.h>


#define LED_REG_MODE1       0x00
#define LED_REG_MODE2       0x01
#define LED_REG_PWM0        0x02
#define LED_REG_PWM1        0x03
#define LED_REG_PWM2        0x04
#define LED_REG_PWM3        0x05
#define LED_REG_GRPPWM      0x06
#define LED_REG_GRPFREQ     0x07
#define LED_REG_LEDOUT      0x08
#define LED_REG_SUBADR1     0x09
#define LED_REG_SUBADR2     0x0A
#define LED_REG_SUBADR3     0x0B
#define LED_REG_ALLCALLADR  0x0C

static struct i2c_client *lamp_client = NULL;


static int lamp_read(u8 reg, u8 *buf, int len)
{
struct i2c_msg msgs[2];
int ret = 0;
int times=5;
char reg_buf = reg;
if(len && buf != NULL && lamp_client!=NULL)
{
while(times<5)
{
msgs[0].addr = lamp_client->addr;
msgs[0].flags = lamp_client->flags & I2C_M_TEN;
msgs[0].len = 1;
msgs[0].buf = &reg_buf;


msgs[1].addr = lamp_client->addr;
msgs[1].flags = lamp_client->flags & I2C_M_TEN;
msgs[1].flags |= I2C_M_RD;
msgs[1].len = len;
msgs[1].buf = buf;


msgs[0].addr = 0xc0;
msgs[1].addr = 0xc0;
ret = i2c_transfer(lamp_client->adapter,msgs,2);
if( ret == 2 )break;
times++;
}
printk("times=%d\n",times);
}
if( times>=5 )
{
printk("lamp fm wirte err\n");
return -1;
}
else
{
//printk("read times=%d\n",times);
return 0;
}
}

static int lamp_write(char* buf, int len)
{
int times = 0,ret=0;;
    struct i2c_msg msg[] = {
        {
            .addr = lamp_client->addr,
            .flags = 0,
            .len = len,
            .buf = buf,
        }
    };

msg[0].addr = 0xc0;

if( lamp_client==NULL || buf==NULL || len<=0)return -1;

while(times < 5)
    {
        ret = i2c_transfer(lamp_client->adapter, &msg, 1);
        if (ret == 1)break;
        times++;
    }
if( times>=5 )
{
printk("lamp fm wirte err\n");
return -1;
}
else
{
//printk("wirte times=%d\n",times);
return 0;
}

}

static int lamp_write_reg(unsigned char addr,unsigned char data)
{
    unsigned char buff[2];
buff[0] = addr;
buff[1] = data;
if((lamp_write(buff,2))<0)
{
printk("lamp  wirte reg err\n");
return -1;
}
return 0;
}

static int lamp_read_reg(u8 reg_addr,u8 *buf,int len)
{

if( lamp_read(reg_addr,buf,len)<0 )
{
printk("lamp  read reg err\n");
}

return 0;
}

void lampsetRGB(
        unsigned char R,
        unsigned char G,
        unsigned char B,
        unsigned char A)
{
    unsigned char bits = 0x00;

    if (R)
        bits |= 0x02;
    if (G)
        bits |= 0x08;
    if (B)
        bits |= 0x20;
    if (A)
        bits |= 0x80;

    
    lamp_write_reg(LED_REG_LEDOUT, bits);

    
    lamp_write_reg(LED_REG_PWM1, R);
    lamp_write_reg(LED_REG_PWM2, G);
    lamp_write_reg(LED_REG_PWM3, B);
    lamp_write_reg(LED_REG_PWM0, A);
//printk("RGBA=0x%02x 0x%02x 0x%02x x%02x bits=0x%x\n",R,G,B,A,bits);
}

static int  pca9632_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
u8 temp[2] = {0};

printk("lamp i2c probe\n");

lamp_client = client;


    lamp_write_reg(LED_REG_MODE1, 0x0F);

    lamp_write_reg(LED_REG_MODE2, 0x05);
    lamp_write_reg(LED_REG_PWM0, 0x00);
    lamp_write_reg(LED_REG_PWM1, 0x00);
    lamp_write_reg(LED_REG_PWM2, 0x00);
    lamp_write_reg(LED_REG_PWM3, 0x00);
    lamp_write_reg(LED_REG_GRPPWM, 0xFF);
    lamp_write_reg(LED_REG_GRPFREQ, 0x00);
    lamp_write_reg(LED_REG_LEDOUT, 0x0);
    lamp_write_reg(LED_REG_GRPFREQ, 0x00);

printk("lamp i2c probe addr=0x%x\n",lamp_client->addr);

printk("lamp name=%s\n",lamp_client->name);

if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
{
printk("lamp i2c probe fail\n");
return -ENODEV;
}

return 0;
}

static int  pca9632_remove(struct i2c_client *client)
{
return 0;
}

static const struct i2c_device_id pca9632_id[] = {
{ "lamp_i2c", 0 },
{ }
};

MODULE_DEVICE_TABLE(i2c, pca9632_id);

static struct of_device_id lamp_dt_ids[] = {
{ .compatible = "lamp_i2c" },
{},
};

struct i2c_driver pca9632_driver = {
.driver = {
.name = "lamp_i2c",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(lamp_dt_ids),
},
.probe = pca9632_probe,
.remove = pca9632_remove,
.id_table = pca9632_id,
};

static int __init pca9632_init(void)
{
return i2c_add_driver(&pca9632_driver);
}

static void __exit pca9632_exit(void)
{
i2c_del_driver(&pca9632_driver);
}

MODULE_AUTHOR("conlan conlan@sziauto.com");
MODULE_DESCRIPTION("PCA9632 driver");
MODULE_LICENSE("GPL");

module_init(pca9632_init);
module_exit(pca9632_exit);

好了,这个就是一个简单的从驱动到应用的例子,希望对大家有用。
沙发#
发布于:2019-07-29 21:04



非常给力啊。感谢分享
If you have nothing to lose, then you can do anything.
yam
yam
论坛版主
论坛版主
  • 社区居民
  • 优秀斑竹
  • VIP会员
  • 荣誉会员
板凳#
发布于:2019-07-30 13:37
地板#
发布于:2019-07-30 13:49
可以多发些图片,把添加的功能点的文件目录结构,编译脚本配置,分享就最完美了,这样别人更能看懂的直接学习使用了。
If you have nothing to lose, then you can do anything.
4楼#
发布于:2021-01-06 23:28
有个简单的方法,把三个GPIO配置到gpio-leds或者pwn-leds模块下,然后在hal层配置一下每个灯的brigheness目录,就能通过android原生的lightsservice设置灯的开关了。
少造一个轮子
5楼#
发布于:2021-01-07 16:44
conlan
论坛版主
论坛版主
6楼#
发布于:2021-01-27 18:12
陆沉子:有个简单的方法,把三个GPIO配置到gpio-leds或者pwn-leds模块下,然后在hal层配置一下每个灯的brigheness目录,就能通过android原生的lightsservice设置灯的开关了。
少造一个轮子
回到原帖
这个是I2C控制的,led可以显示256色的,跟调色板一样。
7楼#
发布于:2021-01-27 18:16
conlan:这个是I2C控制的,led可以显示256色的,跟调色板一样。回到原帖
是的,把GPIO配置成PWM输出,然后配置dts到led-pwm下
conlan
论坛版主
论坛版主
8楼#
发布于:2021-01-27 18:16
陆沉子:是的,把GPIO配置成PWM输出,然后配置dts到led-pwm下回到原帖
嗯,应该也是可以实现,这个当时好像没有那么多GPIO口了,加了一个外挂芯片。
游客

返回顶部