1、在kernel/drivers目录下新建ioctrl文件夹
# cd kernel/drivers
# mkdir ioctrl
在/driver/ioctrl目录下,新建ioctrl.c ,ioctrl.h , Kconfig, Makefile 等4个文件。
2、在Kconfig下添加代码:
config IOCTRL
tristate "io Control"
default y
help
when system setup,change the io state
在Makefile下添加代码:
obj-$(CONFIG_IOCTRL) += ioctrl.o
在ioctrl.c中添加代码:
/*
* Driver for pwm demo on Firefly board ioctrl.
*
* Copyright (C) 2022, Zhongshan T-chip Intelligent Technology Co.,ltd.
* Copyright 2006 Sam Chan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/**********************************************************************
* version control
*
* version: v1.0.0_20191022
* creater: dulc
* creat date: 2019.10.22
* changer:
* chang date:
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IOCTRL_MAJOR 97
struct firefly_ioctrl_info {
int gpio_wireless_en; // 3g/4g power control
int gpio_we_value;
};
static int firefly_ioctrl_probe(struct platform_device *pdev);
// ioctrl operation
ssize_t ioctrl_read( struct file * file, char * buf, size_t count, loff_t * f_ops );
ssize_t ioctrl_write( struct file * file, const char * buf, size_t count, loff_t *f_ops );
long ioctrl_ioctl( struct file *file, unsigned int cmd, unsigned long arg);
int ioctrl_open( struct inode * inode, struct file *file );
int ioctrl_release(struct inode *inode, struct file *file );
int ioctrl_led_control( char cmd, char subcmd );
/*********************************GPIO*************************************/
static struct of_device_id firefly_ioctrl_match_table[] = {
{ .compatible = "firefly,rk3399-gpio1",},
{},
};
static struct platform_driver firefly_ioctrl_driver = {
.driver = {
.name = "firefly-ioctrl",
.owner = THIS_MODULE,
.of_match_table = firefly_ioctrl_match_table,
},
.probe = firefly_ioctrl_probe,
};
/*********************************GPIO*************************************/
// the ioctrl operations device
static const struct file_operations io_ctrl_ops = {
.owner = THIS_MODULE,
.open = ioctrl_open,
.read = ioctrl_read,
.write = ioctrl_write,
.unlocked_ioctl = ioctrl_ioctl,
.release = ioctrl_release,
};
// gpio device
struct firefly_ioctrl_info *ioctrl_device_ctrl = NULL;
ssize_t ioctrl_read( struct file * file, char * buf, size_t count, loff_t * f_ops )
{
ssize_t size = 0;
return size;
}
ssize_t ioctrl_write(struct file * file, const char * buf, size_t count, loff_t *f_ops )
{
ssize_t size = 0;
return size;
}
long ioctrl_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = 0;
if ( cmd == 0 )
{
gpio_direction_output(ioctrl_device_ctrl->gpio_wireless_en, false);
}
else
{
gpio_direction_output(ioctrl_device_ctrl->gpio_wireless_en, true);
}
return ret;
}
int ioctrl_open( struct inode * inode, struct file *file )
{
return 0;
}
int ioctrl_release(struct inode *inode, struct file *file )
{
return 0;
}
static int firefly_ioctrl_probe(struct platform_device *pdev)
{
int gpio;
enum of_gpio_flags flag;
struct firefly_ioctrl_info *gpio_info;
struct device_node *firefly_ioctrl_node = pdev->dev.of_node;
gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct firefly_ioctrl_info *), GFP_KERNEL);
if (!gpio_info) {
dev_err(&pdev->dev, "devm_kzalloc failed!\n");
return -ENOMEM;
}
// 3g/4g power control
gpio = of_get_named_gpio_flags(firefly_ioctrl_node, "firefly-gpio-wireless", 0, &flag);
if (!gpio_is_valid(gpio)) {
dev_err(&pdev->dev, "firefly-gpio-wireless: %d is invalid\n", gpio);
return -ENODEV;
}
if (gpio_request(gpio, "firefly-gpio-wireless")) {
dev_err(&pdev->dev, "firefly-gpio-wireless: %d request failed!\n", gpio);
gpio_free(gpio);
return -ENODEV;
}
printk("ioctrl driver register success!\n");
gpio_info->gpio_wireless_en = gpio;
// gpio_info->gpio_pe_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
gpio_direction_output(gpio_info->gpio_wireless_en, false);
ioctrl_device_ctrl = gpio_info;
return 0;
}
// init the ioctrl driver
static int ioctrl_init(void)
{
int ret = -ENODEV;
int ret_val = 0xFFFFFFFF;
struct class *ioctrl_dev_class;
// register GPIO driver
platform_driver_register(&firefly_ioctrl_driver);
// register driver
ret = register_chrdev( IOCTRL_MAJOR, "ioctrldrive", &io_ctrl_ops );
if ( ret < 0 )
{
printk("register ioctrl driver error! \n");
return ret;
}
// creat class
ioctrl_dev_class = class_create( THIS_MODULE, "ioctrldrive" );
if ( IS_ERR(ioctrl_dev_class) )
{
unregister_chrdev( IOCTRL_MAJOR, "capi20");
return PTR_ERR(ioctrl_dev_class);
}
// creat node
device_create( ioctrl_dev_class, NULL, MKDEV(IOCTRL_MAJOR,0),NULL, "ioctrl");
return ret_val;
}
module_init(ioctrl_init);
static void ioctrl_exit(void)
{
platform_driver_unregister(&firefly_ioctrl_driver);
}
module_exit(ioctrl_exit);
MODULE_AUTHOR("dulc ");
MODULE_DESCRIPTION("Firefly ioctrl demo driver");
MODULE_ALIAS("platform:firefly-ioctrl");
MODULE_LICENSE("GPL");
在kernel/drivers目录下的Makefile文件下,添加以下代码:
obj-$(CONFIG_IOCTRL) += ioctrl/
在kernel/drivers目录下的Kconfig文件下,添加以下代码:
source "drivers/ioctrl/Kconfig"
这时代码默认就编译到了kernel中,在kernel文件夹下,执行指令
# make menuconfig
选择Device Drivers,可看到编译进去的驱动
(默认为选中状态(*),是由于ioctrl文件夹下的Kconfig配置为 tristate "io Control" default y, io Control是名称,default y是默认开启,默认关闭用default n)
3、编写C语言测试程序。
在 your_android_src/external目录下,新建文件夹
# mkdir ioctrltest
在该文件夹下添加两个文件:Android.mk 、ioctrltest.c
在Android.mk文件中添加代码:
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= ioctrltest.c
LOCAL_MODULE:=ioctrlapp
include $(BUILD_EXECUTABLE)
其中 LOCAL_SRC_FILES为测试程序的源文件,LOCAL_MODULE为生成的可执行文件。
在ioctrltest.c中添加代码:
#include
#include
#include
#include
#include
#define DEVICE_NAME "/dev/ioctrl"
int main( int argc, char ** argv )
{
int fd;
char cmd, subcmd;
int i;
printf("\n -----turn on the 3g power ----- \n");
fd = open(DEVICE_NAME, O_RDWR );
printf("fd = %d \n", fd );
if ( fd == -1 )
{
printf("open device %s error \n", DEVICE_NAME );
}
else
{
// turn on the 3g power
ioctl(fd, 1, 0);
}
}
在安卓目录下,执行
# make ioctrlapp
会在 out/target/product/rk3399_firefly_box/system/bin/ioctrlapp 生成相应的ioctrlapp (目录可能不同,根据自己实际情况操作)
把ioctrlapp拷贝到优盘中,启动rk3399,将优盘插入3399,然后在调试模式下,执行如下操作,可运行该程序
$su
#cp mnt/medea_rw/(upan_name)/ioctrlapp /mnt/ioctrlapp
#cd mnt
./ioctrlapp
注:在dev下生成的ioctrl驱动,要获取权限才可打开,临时获取权限,使用以下指令:
# chmod 777 /dev/ioctrl
永久获取权限,参照以下链接执行即可:
https://blog.csdn.net/d4l6c8/article/details/101345756
4、开启启动该程序ioctrlapp。
在device/rockchip/rk3399/device.mk中添加以下语句:
PRODUCT_COPY_FILES += \
out/target/product/rk3399_firefly_aiojd4_mipi_box/system/bin/ioctrlapp:system/bin/ioctrlapp
在/device/rockchip/rk3399/rk3399_firefly_aiojd4_mipi_box目录下的init.rc 下添加以下语句:
#dlc add
service service_ioctrl /system/bin/ioctrlapp
user root
group root
disabled
oneshot
on property:sys.boot_completed=1
注意 service_ioctrl这个服务名称不能超过16个字节,否则认为该服务有问题,不会启动该服务。
在/device/rockchip/common/sepolicy目录下新增文件service_ioctrl.te,添加如下代码:
type service_ioctrl, domain;
type service_ioctrl_exec, exec_type, file_type;
permissive service_ioctrl;
init_daemon_domain(service_ioctrl)
在/device/rockchip/common/sepolicy目录下新增文件ioctrl_device.te,添加如下代码:
type ioctrl_device,file_type,dev_type;
在file_contexts文件中添加如下代码:
#service_ioctrl
/system/bin/ioctrlapp u:object_r:service_ioctrl_exec:s0
/dev/ioctrl u:object_r:ioctrl_device:s0
到这里基本完成,路径根据自己的工程修改。