JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
1.DTS设备树文件匹配驱动配置
46 / {
47 model = "AIO-3399JD4 Board mipi (Android)";
48 compatible = "rockchip,android", "rockchip,rk3399-raindi-mipi", "rockchip,rk3399";
49
50 rd_gpio: rd_gpio{
51 status = "okay";
52 compatible = "rockchip,rd_gpio";
53 rd-gpio1 = <&gpio1 9 GPIO_ACTIVE_LOW>;//GPIO1_B1 -> GPIO41
54 rd-gpio2 = <&gpio2 28 GPIO_ACTIVE_LOW>;//GPIO2_D4 -> GPIO92 GPIO2_A1 -> 65
55 };
56 };
2.gpio驱动:kernel/drivers/misc/rd_gpio.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/semaphore.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <asm/delay.h>
#if 0
#define GPIO_IOC_MAGIC 'G'
#define IOCTL_GPIO_SETINPUT _IOW(GPIO_IOC_MAGIC, 0, int)
#define IOCTL_GPIO_SETOUTHIGH _IOW(GPIO_IOC_MAGIC, 1, int)
#define IOCTL_GPIO_SETOUTLOW _IOW(GPIO_IOC_MAGIC, 2, int)
#define IOCTL_GPIO_GETVALUE _IOR(GPIO_IOC_MAGIC, 3, int)
#define GPIO_IOC_MAXNR 3
#else
#define GPIO_IOC_MAGIC 0x90
#define GPIO_BASE_OFFSET 911
#define GPIO_IOCQMODE _IOR(GPIO_IOC_MAGIC, 0x01, uint32_t)
#define GPIO_IOCTMODE0 _IOW(GPIO_IOC_MAGIC, 0x02, uint32_t)
#define GPIO_IOCTMODE1 _IOW(GPIO_IOC_MAGIC, 0x03, uint32_t)
#define GPIO_IOCTMODE2 _IOW(GPIO_IOC_MAGIC, 0x04, uint32_t)
#define GPIO_IOCTMODE3 _IOW(GPIO_IOC_MAGIC, 0x05, uint32_t)
#define GPIO_IOCQDIR _IOR(GPIO_IOC_MAGIC, 0x06, uint32_t)
#define GPIO_IOCSDIRIN _IOW(GPIO_IOC_MAGIC, 0x07, uint32_t)
#define GPIO_IOCSDIROUT _IOW(GPIO_IOC_MAGIC, 0x08, uint32_t)
#define GPIO_IOCQPULLEN _IOR(GPIO_IOC_MAGIC, 0x09, uint32_t)
#define GPIO_IOCSPULLENABLE _IOW(GPIO_IOC_MAGIC, 0x0A, uint32_t)
#define GPIO_IOCSPULLDISABLE _IOW(GPIO_IOC_MAGIC, 0x0B, uint32_t)
#define GPIO_IOCQPULL _IOR(GPIO_IOC_MAGIC, 0x0C, uint32_t)
#define GPIO_IOCSPULLDOWN _IOW(GPIO_IOC_MAGIC, 0x0D, uint32_t)
#define GPIO_IOCSPULLUP _IOW(GPIO_IOC_MAGIC, 0x0E, uint32_t)
#define GPIO_IOCQINV _IOR(GPIO_IOC_MAGIC, 0x0F, uint32_t)
#define GPIO_IOCSINVENABLE _IOW(GPIO_IOC_MAGIC, 0x10, uint32_t)
#define GPIO_IOCSINVDISABLE _IOW(GPIO_IOC_MAGIC, 0x11, uint32_t)
#define GPIO_IOCQDATAIN _IOR(GPIO_IOC_MAGIC, 0x12, uint32_t)
#define GPIO_IOCQDATAOUT _IOR(GPIO_IOC_MAGIC, 0x13, uint32_t)
#define GPIO_IOCSDATALOW _IOW(GPIO_IOC_MAGIC, 0x14, uint32_t)
#define GPIO_IOCSDATAHIGH _IOW(GPIO_IOC_MAGIC, 0x15, uint32_t)
#endif
struct rd_gpio_info{
unsigned rd_gpio1;
unsigned rd_gpio2;
}rd_gpio;
static ssize_t rd_gpios_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE,"PIN0:%d.PIN1:%d.\n",gpio_get_value(rd_gpio.rd_gpio1),
gpio_get_value(rd_gpio.rd_gpio2));
}
static ssize_t rd_gpios_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
int value;
int gpioNo;
if (sscanf(buf, "%d,%d", &gpioNo,&value) != 2) {
printk(KERN_ERR "%s: sscanf %s is wrong \n", __func__,buf);
return -EINVAL;
}
printk("setup gpio%d:%d\n",gpioNo,value);
gpio_direction_output((uint16_t)gpioNo, value);
return size;
}
//static DEVICE_ATTR(gpios, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, rd_gpios_show, rd_gpios_store);
static DEVICE_ATTR(gpios, S_IRUSR | S_IWUSR, rd_gpios_show, rd_gpios_store);
static struct attribute *rd_sysfs_attr[] = {
&dev_attr_gpios.attr,
NULL
};
static struct attribute_group rd_attribute_group = {
.attrs = rd_sysfs_attr,
};
static int rd_gpio_is_valid(u32 pin)
{
if(!gpio_is_valid(pin)){
printk("rd-gpio: %d is invalid\n", pin);
return -ENODEV;
}
return 0;
}
/*****************************************************************************/
/* File operation */
/*****************************************************************************/
static int gpio_open(struct inode *inode, struct file *file)
{
printk("raindi gpio open \n");
return 0;
}
/*---------------------------------------------------------------------------*/
static int gpio_release(struct inode *inode, struct file *file)
{
printk("raindi gpio release\n");
return 0;
}
static long gpio_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
long ret = 0;
u32 pin;
pin = (u32)arg;
printk("setup rd gpio cmd:%x pin:%d\n",cmd,pin);
if(!rd_gpio_is_valid(pin)){
switch(cmd)
{
case GPIO_IOCQMODE:
case GPIO_IOCTMODE0:
case GPIO_IOCTMODE1:
case GPIO_IOCTMODE2:
case GPIO_IOCTMODE3:
case GPIO_IOCQDIR:
case GPIO_IOCSDIRIN:
{
gpio_direction_input(pin);
break;
}
case GPIO_IOCSDIROUT:
case GPIO_IOCQPULLEN:
case GPIO_IOCSPULLENABLE:
case GPIO_IOCSPULLDISABLE:
case GPIO_IOCQPULL:
case GPIO_IOCSPULLDOWN:
case GPIO_IOCSPULLUP:
case GPIO_IOCQINV:
case GPIO_IOCSINVENABLE:
case GPIO_IOCSINVDISABLE:
break;
case GPIO_IOCQDATAIN:
case GPIO_IOCQDATAOUT:
{
ret = __gpio_get_value(pin);
break;
}
case GPIO_IOCSDATALOW:
{
gpio_direction_output(pin, 0);
break;
}
case GPIO_IOCSDATAHIGH:
{
gpio_direction_output(pin, 1);
break;
}
default:
{
ret = -EPERM;
break;
}
}
}else {
ret = -EPERM ;
}
if (ret == -EACCES)
printk(" cmd = 0x%8X, invalid pointer\n", cmd);
else if (ret < 0)
printk(" cmd = 0x%8X, err = %ld\n", cmd, ret);
return ret;
}
static struct file_operations rd_gpio_fops =
{
.owner= THIS_MODULE,
.unlocked_ioctl= gpio_ioctl,
.compat_ioctl = gpio_ioctl,
.open= gpio_open,
.release= gpio_release,
};
static struct miscdevice rd_gpio_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mtgpio",
.fops = &rd_gpio_fops,
};
static int rd_gpio_probe(struct platform_device *pdev)
{
int ret = 0;
int gpio;
int enable_value = 0;
enum of_gpio_flags flag;
struct rd_gpio_info *gpio_info;
struct device_node *rd_gpio_node = pdev->dev.of_node;
struct miscdevice *rd_misc = &rd_gpio_device;
gpio_info = devm_kzalloc(&pdev->dev,sizeof(*gpio_info), GFP_KERNEL);
if (!gpio_info) {
dev_err(&pdev->dev, "devm_kzalloc failed!\n");
return -ENOMEM;
}
gpio = of_get_named_gpio_flags(rd_gpio_node, "rd-gpio1", 0, &flag);
if (!gpio_is_valid(gpio)) {
dev_err(&pdev->dev, "rd-gpio1: %d is invalid\n", gpio);
return -ENODEV;
}
if (gpio_request(gpio, "rd-gpio1")) {
dev_err(&pdev->dev, "rd-gpio1: %d request failed!\n", gpio);
gpio_free(gpio);
return -ENODEV;
}
rd_gpio.rd_gpio1 = gpio;
enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
gpio_direction_output(gpio, enable_value);
printk("rd_gpio1 gpio output: %d\n", enable_value);
gpio = of_get_named_gpio_flags(rd_gpio_node, "rd-gpio2", 0, &flag);
if (!gpio_is_valid(gpio)) {
dev_err(&pdev->dev, "rd-gpio2: %d is invalid\n", gpio);
return -ENODEV;
}
if(gpio_request(gpio, "rd-gpio2")){
dev_err(&pdev->dev, "rd2-gpio2: %d request failed!\n", gpio);
gpio_free(gpio);
return -ENODEV;
}
rd_gpio.rd_gpio2 = gpio;
enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
gpio_direction_output(gpio, enable_value);
printk("rd_gpio2 gpio output: %d\n", enable_value);
ret = sysfs_create_group(&pdev->dev.kobj, &rd_attribute_group);
//ret = class_register(&rd_class);
if (ret < 0) {
printk("rd Sysfs registration failed.\n");
devm_kfree(&pdev->dev,gpio_info);
}
if ((ret = misc_register(rd_misc)))
dev_err(&pdev->dev,"register rd_gpio misc device failed\n");
return 0;
}
static const struct of_device_id rd_dt_ids[] = {
{ .compatible = "rockchip,rd_gpio", },
{}
};
static struct platform_driver rd_gpio_driver = {
.driver = {
.name = "rd_gpio",
.owner = THIS_MODULE,
.of_match_table = rd_dt_ids,
},
.probe = rd_gpio_probe,
};
static int __init rd_gpio_init(void)
{
return platform_driver_register(&rd_gpio_driver);
}
static void __exit rd_gpio_exit(void)
{
platform_driver_unregister(&rd_gpio_driver);
}
module_init(rd_gpio_init);
module_exit(rd_gpio_exit);
MODULE_DESCRIPTION("Driver for GPIO");
MODULE_AUTHOR("w");
MODULE_LICENSE("GPL");
3.在同级目录下Makefile文件添加编译
obj-y += rd_gpio.o