阅读:12998回复:8
简单的JNI例子
客户要求做一个可以调节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 = ®_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
非常给力啊。感谢分享 |
|
|
地板#
发布于:2019-07-30 13:49
可以多发些图片,把添加的功能点的文件目录结构,编译脚本配置,分享就最完美了,这样别人更能看懂的直接学习使用了。
|
|
|
4楼#
发布于:2021-01-06 23:28
有个简单的方法,把三个GPIO配置到gpio-leds或者pwn-leds模块下,然后在hal层配置一下每个灯的brigheness目录,就能通过android原生的lightsservice设置灯的开关了。
少造一个轮子 |
|
6楼#
发布于:2021-01-27 18:12
|
|
7楼#
发布于:2021-01-27 18:16
|
|
8楼#
发布于:2021-01-27 18:16
|
|