客户需求需要提供4个接口使用4个led灯的开关
分析:不使用jni方式,只需要编写驱动为客户提供4个操作节点,让客户在上层通过写1或者0方式控制这4个节点实现4个灯的开关
操作节点:
led1:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control
led2:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control
led3:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control
led4:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control
开灯:往节点写1 表示开灯 如下:
led1 开灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control" , “1”);
led2 开灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control" , “1”);
led3 开灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control" , “1”);
led4 开灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control" , “1”);
关灯:往节点写0 表示关灯 如下:
led1 关灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control" , “0”);
led2 关灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control" , “0”);
led3 关灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control" , “0”);
led4 关灯: write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control" , “0”);
上层app write方法参考:
import java.io.File;
import java.io.FileWriter;
private void write(String path , String content) {
FileWriter fw = null;
try {
File file = new File(path);
if (file.exists()) {
fw = new FileWriter(file, true);
fw.write(content);
}
} catch (Exception ex) {
Log.i("elink", "write error = "+ex.toString());
} finally {
try {
if (fw != null)
fw.close();
} catch (Exception ex) {
}
}
}
1 查看原理图得知这四个灯的控制引脚分别为:gpio4 gpio5 gpio6 gpio7,配置相关的dts
output_led_ctrl: output_led_ctrl {
compatible = "rockchip,output_led_ctrl";
status = "okay";
led_en1-gpio = <&pio 4 0>;
led_en2-gpio-gpio = <&pio 5 0>;
led_en3-gpio-gpio = <&pio 6 0>;
led_en4-gpio-gpio = <&pio 7 0>;
};
2 编写output_led_ctrl.c驱动
/**********************************************************************
* dts
output_led_ctrl: output_led_ctrl {
compatible = "rockchip,output_led_ctrl";
status = "okay";
led_en1-gpio = <&pio 4 0>;
led_en2-gpio-gpio = <&pio 5 0>;
led_en3-gpio-gpio = <&pio 6 0>;
led_en4-gpio-gpio = <&pio 7 0>;
};
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control" , "1");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control" , "0");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control" , "1");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control" , "0");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control" , "1");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control" , "0");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control" , "1");
write("/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control" , "0");
***********************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define TORCH_DEVNAME "led_contorl_by_elink"//节点名称
static dev_t torch_devno;//设备号
static struct class *torch_class;//class类
static struct device *led_device;//设备
static int debug_status = 0;
#define TAG " "
#define SET_LEVEL KERN_INFO
#define err_msg(fmt, args...) printk(KERN_ERR TAG "error " fmt"\n", ##args)
#define usr_msg(fmt, args...) do { \
if(debug_status) \
printk(SET_LEVEL TAG fmt"\n", ##args); \
} while(0)
#define LED_CTRL_DEV_NAME "led_contorl_by_elink"
#define USING_SYS_FS 1
#if USING_SYS_FS
static int led_one_en_ctrl_status = 0;
static int led_two_en_ctrl_status = 0;
static int led_three_en_ctrl_status = 0;
static int led_four_en_ctrl_status = 0;
#define PAGE_LED_CTRL_ELINK_SIZE 10
static int led_en1_gpio;
static int led_en2_gpio;
static int led_en3_gpio;
static int led_en4_gpio;
#endif
static const struct of_device_id led_ctrl_match_table[] = {
{ .compatible = "mediatek,output_led_ctrl", },
{/* KEEP THIS */},
};
MODULE_DEVICE_TABLE(of, led_ctrl_match_table);
/*------------------------------------------------------------------------------------*/
struct led_info {
struct platform_device * pdev_bk;
};
struct mutex lock;
/**----------------------------------------------------------------------------------*/
static int usr_get_dts_info(struct led_info * info)
{
int ret;
struct device_node *node = info->pdev_bk->dev.of_node;
if(!node) {
err_msg("in func: %s, cannot find node", __func__);
return -ENXIO;
}
led_en1_gpio = of_get_named_gpio(node, "led_en1_gpio", 0);
if(!gpio_is_valid(led_en1_gpio)) {
err_msg("get gpio led_en1_gpio.");
} else {
ret = gpio_request_one(led_en1_gpio, GPIOF_OUT_INIT_LOW, "led_en1_gpio");
if(ret < 0) {
err_msg("info->led_en1_gpio request.");
}
}
usr_msg("moved in func: %s led_en1_gpio = %d \n", __func__,led_en1_gpio);
led_en2_gpio= of_get_named_gpio(node, "led_en2_gpio", 0);
if(!gpio_is_valid(led_en2_gpio)) {
err_msg("get led_en2_gpio.");
} else {
ret = gpio_request_one(led_en2_gpio, GPIOF_OUT_INIT_LOW, "led_en2_gpio");
if(ret < 0) {
err_msg("led_en2_gpio request.");
}
}
usr_msg("moved in func: %s led_en2_gpio = %d \n", __func__,led_en2_gpio);
led_en3_gpio = of_get_named_gpio(node, "led_en3_gpio", 0);
if(!gpio_is_valid(led_en3_gpio)) {
err_msg("get led_en3_gpio.");
} else {
ret = gpio_request_one(led_en3_gpio, GPIOF_OUT_INIT_LOW, "led_en3_gpio");
if(ret < 0) {
err_msg("led_en3_gpio request.");
}
}
usr_msg("moved in func: %s led_en3_gpio = %d \n", __func__,led_en3_gpio);
led_en4_gpio = of_get_named_gpio(node, "led_en4_gpio", 0);
if(!gpio_is_valid(led_en4_gpio)) {
err_msg("get led_en4_gpio.");
} else {
ret = gpio_request_one(led_en4_gpio, GPIOF_OUT_INIT_LOW, "led_en4_gpio");
if(ret < 0) {
err_msg("led_en4_gpio request.");
}
}
usr_msg("moved in func: %s led_en4_gpio = %d \n", __func__,led_en4_gpio);
usr_msg("in func: %s, gpio_get_value(led_en2_gpio) = %d gpio_get_value(led_en4_gpio) = %d \n", __func__, gpio_get_value(led_en2_gpio),gpio_get_value(led_en4_gpio));
if(led_en4_gpio > 0)
gpio_set_value(led_en4_gpio, 0);
usr_msg("in func: %s, gpio_get_value(led_en2_gpio) = %d gpio_get_value(led_en4_gpio) = %d \n", __func__, gpio_get_value(led_en2_gpio),gpio_get_value(led_en4_gpio));
return 0;
}
#if USING_SYS_FS
static ssize_t led_one_control_show(struct device *dev, struct device_attribute *attr, char *buf)
{
usr_msg("moved in func: %s led_one_en_ctrl_status = %d \n", __func__,led_one_en_ctrl_status);
return snprintf(buf, PAGE_LED_CTRL_ELINK_SIZE,"%d\n", led_one_en_ctrl_status);
}
static ssize_t led_one_control_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int temp;
temp = simple_strtol(buf, NULL, 10);//把字符串转为数字
led_one_en_ctrl_status = temp;
usr_msg("in func: %s, led_one_en_ctrl_status = %d", __func__, led_one_en_ctrl_status);
usr_msg("in func: %s, count = %d", __func__, count);
if(led_one_en_ctrl_status == 1) {
usr_msg("in func: %s, set led_en1_gpio output to high", __func__);
if(led_en1_gpio > 0)
gpio_set_value(led_en1_gpio, 1);
} else if(led_one_en_ctrl_status == 0){
usr_msg("in func: %s, set led_en1_gpio output to low", __func__);
if(led_en1_gpio > 0)
gpio_set_value(led_en1_gpio, 0);
}else
usr_msg("dsy invalid parameter,the led_one_en_ctrl_status must be 1 or 0\n");
usr_msg("in func: %s,led_one_en_ctrl_status = %d gpio_get_value(led_en1_gpio) = %d", __func__, led_one_en_ctrl_status,gpio_get_value(led_en1_gpio));
return count;
}
static ssize_t led_two_control_show(struct device *dev, struct device_attribute *attr, char *buf)
{
usr_msg("moved in func: %s led_two_en_ctrl_status = %d \n", __func__,led_two_en_ctrl_status);
return snprintf(buf, PAGE_LED_CTRL_ELINK_SIZE,"%d\n", led_two_en_ctrl_status);
}
static ssize_t led_two_control_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int temp;
temp = simple_strtol(buf, NULL, 10);//把字符串转为数字
led_two_en_ctrl_status = temp;
usr_msg("in func: %s, led_two_en_ctrl_status = %d", __func__, led_two_en_ctrl_status);
usr_msg("in func: %s, count = %d", __func__, count);
if(led_two_en_ctrl_status == 1) {
usr_msg("in func: %s, set led_en2_gpio output to high", __func__);
if(led_en2_gpio > 0)
gpio_set_value(led_en2_gpio, 1);
} else if(led_two_en_ctrl_status == 0){
usr_msg("in func: %s, set led_en2_gpio output to low", __func__);
if(led_en2_gpio > 0)
gpio_set_value(led_en2_gpio, 0);
}else
usr_msg("dsy invalid parameter,the led_two_en_ctrl_status must be 1 or 0\n");
usr_msg("in func: %s,led_two_en_ctrl_status = %d gpio_get_value(led_en2_gpio) = %d", __func__, led_two_en_ctrl_status,gpio_get_value(led_en2_gpio));
return count;
}
static ssize_t led_three_control_show(struct device *dev, struct device_attribute *attr, char *buf)
{
usr_msg("moved in func: %s", __func__);
usr_msg("moved in func: %s led_three_en_ctrl_status = %d \n", __func__,led_three_en_ctrl_status);
return snprintf(buf, PAGE_LED_CTRL_ELINK_SIZE,"%d\n", led_three_en_ctrl_status);
}
static ssize_t led_three_control_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int temp;
temp = simple_strtol(buf, NULL, 10);//把字符串转为数字
led_three_en_ctrl_status = temp;
usr_msg("in func: %s, count = %d", __func__, count);
usr_msg("in func: %s, led_three_en_ctrl_status = %d", __func__, led_three_en_ctrl_status);
if(led_three_en_ctrl_status == 1) {
usr_msg("in func: %s, set led_en3_gpio output to high", __func__);
if(led_en3_gpio > 0)
gpio_set_value(led_en3_gpio, 1);
} else if(led_three_en_ctrl_status == 0){
usr_msg("in func: %s, set led_en3_gpio output to low", __func__);
if(led_en3_gpio > 0)
gpio_set_value(led_en3_gpio, 0);
}else
usr_msg("dsy invalid parameter,the led_three_en_ctrl_status must be 1 or 0\n");
usr_msg("in func: %s, led_three_en_ctrl_status = %d gpio_get_value(led_en3_gpio) = %d", __func__, led_three_en_ctrl_status,gpio_get_value(led_en3_gpio));
return count;
}
static ssize_t led_four_control_show(struct device *dev, struct device_attribute *attr, char *buf)
{
usr_msg("moved in func: %s led_four_en_ctrl_status = %d \n", __func__,led_four_en_ctrl_status);
return snprintf(buf, PAGE_LED_CTRL_ELINK_SIZE,"%d\n", led_four_en_ctrl_status);
}
static ssize_t led_four_control_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int temp;
temp = simple_strtol(buf, NULL, 10);//把字符串转为数字
led_four_en_ctrl_status = temp;
usr_msg("in func: %s, led_four_en_ctrl_status = %d", __func__, led_four_en_ctrl_status);
usr_msg("in func: %s, count = %d", __func__, count);
if(led_four_en_ctrl_status == 1) {
usr_msg("in func: %s, set led_en4_gpio output to high", __func__);
if(led_en4_gpio > 0)
gpio_set_value(led_en4_gpio, 1);
} else if(led_four_en_ctrl_status == 0){
usr_msg("in func: %s, set led_en4_gpio output to low", __func__);
if(led_en4_gpio > 0)
gpio_set_value(led_en4_gpio, 0);
}else
usr_msg("dsy invalid parameter,the led_four_en_ctrl_status must be 1 or 0\n");
usr_msg("in func: %s, led_three_en_ctrl_status = %d gpio_get_value(led_en4_gpio) = %d", __func__, led_three_en_ctrl_status,gpio_get_value(led_en4_gpio));
return count;
}
//定义设备属性节点led_one_control led_two_control led_three_control led_four_control,和show函数,store函数
static DEVICE_ATTR(led_one_control, 0664, led_one_control_show, led_one_control_store);
static DEVICE_ATTR(led_two_control, 0664, led_two_control_show, led_two_control_store);
static DEVICE_ATTR(led_three_control, 0664, led_three_control_show, led_three_control_store);
static DEVICE_ATTR(led_four_control, 0664, led_four_control_show, led_four_control_store);
static int led_ctrl_sysfs_create(struct platform_device * pdev)
{
int ret = 0;
int rc = 0;
usr_msg("1111111moved in function: %s", __func__);
//申请设备号--下面需要用的这个设备号
ret = alloc_chrdev_region(&torch_devno, 0, 1, TORCH_DEVNAME);
if (ret) {//申请成功
usr_msg("dsy [led_ctrl] alloc_chrdev_region fail: %d ~", ret);
//goto torch_chrdev_error; 这里应该跳到unregister函数,懒得写
} else {//申请失败
usr_msg("dsy [led_ctrl] major: %d, minor: %d ~", MAJOR(torch_devno),
MINOR(torch_devno));
}
//在sys/class创建torch_class 类
torch_class = class_create(THIS_MODULE, TORCH_DEVNAME);
if (IS_ERR(torch_class)) {//创建失败
usr_msg("dsy Unable to create class:torch_class\n");
}
//在sys/class/torch_class/下创建设备节点
led_device =device_create(torch_class, NULL, torch_devno,
NULL, TORCH_DEVNAME);
if(NULL == led_device)//创建失败
usr_msg("dsy [torch_init] device_create led_device fail \n");
usr_msg("moved in function: device_create led_device succed %s", __func__);
//在sys/class/torch_class/torch_class下创建属性文件led_one_control
rc = device_create_file(led_device, &dev_attr_led_one_control);
if (rc) {
usr_msg("in function: %s, create fs led1_runing_reboot failed", __func__);
return -1;
}
rc = device_create_file(led_device, &dev_attr_led_two_control);
if (rc) {
usr_msg("in function: %s, create fs led2_runing_reboot failed", __func__);
return -1;
}
rc = device_create_file(led_device, &dev_attr_led_three_control);
if (rc) {
usr_msg("in function: %s, create fs led3_runing_reboot failed", __func__);
return -1;
}
rc = device_create_file(led_device, &dev_attr_led_four_control);
if (rc) {
usr_msg("in function: %s, create fs led4_runing_reboot failed", __func__);
return -1;
}
usr_msg("22222moved in function: %s end ", __func__);
return 0;
}
#endif
static int led_ctrl_probe(struct platform_device *pdev)
{
int ret;
struct led_info * info = devm_kmalloc(&pdev->dev, sizeof(struct led_info), GFP_KERNEL);
if(IS_ERR(info)) {
usr_msg("error: devm_kmalloc");
return -ENOMEM;
}
usr_msg("moved in function: %s", __func__);
mutex_init(&lock);
info->pdev_bk = pdev;
ret = usr_get_dts_info(info);
if(ret < 0) {
usr_msg("error: get gpio dts info");
goto error1;
}
#if 0
if(led_en1_gpio > 0)
gpio_set_value(led_en1_gpio, 1);
if(led_en2_gpio > 0)
gpio_set_value(led_en2_gpio, 1);
if(led_en3_gpio > 0)
gpio_set_value(led_en3_gpio, 1);
if(led_en4_gpio > 0)
gpio_set_value(led_en4_gpio, 1);
mdelay(1000);
if(led_en1_gpio > 0)
gpio_set_value(led_en1_gpio, 0);
if(led_en2_gpio > 0)
gpio_set_value(led_en2_gpio, 0);
if(led_en3_gpio > 0)
gpio_set_value(led_en3_gpio, 0);
if(led_en4_gpio > 0)
gpio_set_value(led_en4_gpio, 0);
#endif
usr_msg("in func: %s, gpio_get_value(led_en2_gpio) = %d gpio_get_value(led_en4_gpio) = %d \n", __func__, gpio_get_value(led_en2_gpio),gpio_get_value(led_en4_gpio));
if(led_en4_gpio > 0)
gpio_set_value(led_en4_gpio, 0);
usr_msg("in func: %s, gpio_get_value(led_en2_gpio) = %d gpio_get_value(led_en4_gpio) = %d \n", __func__, gpio_get_value(led_en2_gpio),gpio_get_value(led_en4_gpio));
dev_set_drvdata(&pdev->dev, (void *) info);
#if USING_SYS_FS
ret = led_ctrl_sysfs_create(pdev);
if(ret < 0) {
usr_msg("create sysfs failed.");
goto error1;
}
usr_msg("11111111moved in function: %s", __func__);
#endif
usr_msg("222222222moved in function: %s", __func__);
return 0;
error1:
return ret;
}
static int led_ctrl_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver led_ctrl_driver = {
.probe = led_ctrl_probe,
.remove = led_ctrl_remove,
.driver = {
.name =LED_CTRL_DEV_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(led_ctrl_match_table),
},
};
static int __init led_ctrl_init(void)
{
int err;
usr_msg("moved in func: %s", __func__);
err = platform_driver_register(&led_ctrl_driver);
if(err)
{
printk("dsy failed to register driver\n");
return -ENODEV;
}
return err;
}
static void __exit led_ctrl_exit(void)
{
usr_msg("moved in func: %s", __func__);
platform_driver_unregister(&led_ctrl_driver);
}
module_init(led_ctrl_init);
module_exit(led_ctrl_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("dongshiyi");
MODULE_DESCRIPTION("led_ctrl_driver control loop");
MODULE_ALIAS("led_ctrl_driver");
生成的相关节点为:led1:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control
led2:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control
led3:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control
led4:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control
3 为这4个节点赋予相关的权限,目的是让客户有权限直接操作这4个节点
3.1 赋予666权限
修改文件\device\mediatek\mt8167\init.mt8167.rc
#added by dongshiyi for led control start 20200507
chmod 0666 /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_one_control
chown root system /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_one_control
chmod 0666 /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_two_control
chown root system /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_two_control
chmod 0666 /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_three_control
chown root system /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_three_control
chmod 0666 /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_four_control
chown root system /sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_four_control
#added by dongshiyi for led control end 20200507
3.2 增加相关的策略
\device\mediatek\mt8167\sepolicy\bsp\file_contexts
#added by dongshiyi for led control start 20200507
/sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_one_control u:object_r:system_app_led_contorl_by_elink_file:s0
/sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_two_control u:object_r:system_app_led_contorl_by_elink_file:s0
/sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_three_control u:object_r:system_app_led_contorl_by_elink_file:s0
/sys/devices/virtual/led_contorl_by_elink/led_contorl_by_elink/led_four_control u:object_r:system_app_led_contorl_by_elink_file:s0
#added by dongshiyi for led control end 20200507
\device\mediatek\mt8167\sepolicy\bsp\file.te
#added by dongshiyi for led control start 20200507
type system_app_led_contorl_by_elink_file,fs_type,sysfs_type;
#added by dongshiyi for led control end 20200507
\device\mediatek\mt8167\sepolicy\basic\cameraserver.te
#added by dongshiyi for led control start 20200507
allow system_app system_app_zigbee_bm023_by_elink_file:file rw_file_perms;
#added by dongshiyi for led control end 20200507
调试过程中可使用adb进行调试,具体参考如下步骤
aiot8362am3_bsp:/sys/class/led_contorl_by_elink/led_contorl_by_elink #
cat led_one_control //查看/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control的值 值为0代表led1灯是关闭的,值为1表示led1灯是打开的
0
aiot8362am3_bsp:/sys/class/led_contorl_by_elink/led_contorl_by_elink #
echo 1 > led_one_control //往节点里写1代表要打开led1灯
aiot8362am3_bsp:/sys/class/led_contorl_by_elink/led_contorl_by_elink #
cat led_one_control //此时再查sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control的值,因为往节点写1了,所以此时led1灯是打开了
1
aiot8362am3_bsp:/sys/class/led_contorl_by_elink/led_contorl_by_elink #
echo 0 > led_one_control //如果此时往节点sys/class/led_contorl_by_elink/led_contorl_by_elink/led_one_control写0可以实现led1灯关闭
类似的其他三个节点
led2:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_two_control
led3:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_three_control
led4:/sys/class/led_contorl_by_elink/led_contorl_by_elink/led_four_control
也可以按照上面的调试方法验证。