1. Driver part (图方便,随便在一个文件中申请了一个杂项设备,有时候想,为什么不是字符设备,查阅相关信息,得知杂项设备驱动是一种特殊的字符设备驱动,节省了主设备号,使用简单。)
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#define MISC_NAME "led"
#define MISC_IOC_MAGIC 'L'
#define RK_FBIOSET_SET_LOGO _IOW(MISC_IOC_MAGIC, 0x00, int)
int sys_indicator_gpio;
static long logo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int on;
pr_info("%s cmd:%d arg:%d", __FUNCTION__, cmd, arg);
switch (cmd) {
case RK_FBIOSET_SET_LOGO:
if (argp == NULL) {
pr_info("invalid argument.\n");
return -EINVAL;
}
if (copy_from_user(&on, argp, sizeof(on)))
return -EFAULT;
if (on == 0) {
gpio_direction_output(sys_indicator_gpio, 0);
} else {
gpio_direction_output(sys_indicator_gpio, 1);
}
break;
}
return 0;
}
static const struct file_operations logo_misc_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = logo_ioctl,
};
static struct miscdevice logo_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = MISC_NAME,
.fops = &logo_misc_fops,
};
static int xxx_probe(struct platform_device *pdev)
{
...
sys_indicator_gpio = of_get_named_gpio_flags(node, "sys_indicator_gpios", 0,
&flags_sys_indicator);
misc_register(&logo_misc_device);
return 0;
}
static int xxx_remove(struct platform_device *pdev)
{
...
misc_deregister(&logo_misc_device);
return 0;
}
2.?system/core/rootdir/ueventd.rc 下添加设备读写权限,如 /dev/led ? ?0666 ? ?root ? ?root
3. Hal lay?hardware/libhardware/modules/led/led.c
#include <hardware/hardware.h>
#include <hardware/logo.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#define DEVICE_NAME "/dev/led"
#define MISC_IOC_MAGIC 'L'
#define RK_FBIOSET_SET_LOGO _IOW(MISC_IOC_MAGIC, 0x00, int)
int logo_device_close(struct hw_device_t* device)
{
struct logo_control_device_t *logo_dev = (struct logo_control_device_t*)device;
if(logo_dev)
{
free(logo_dev);
}
close(logo_dev->fd);
return 0;
}
int logo_set(struct logo_control_device_t *dev, int on)
{
if (ioctl(dev->fd, RK_FBIOSET_SET_LOGO, &on) < 0)
{
ALOGE("%s: error.", __FUNCTION__);
return -1;
}
return 0;
}
static int logo_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
struct logo_control_device_t *dev;
dev = (struct logo_control_device_t *)calloc(1, sizeof(struct logo_control_device_t));
if (!dev)
{
ALOGE("logo led open error");
return -ENOMEM;
}
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t *)module;
dev->common.close = logo_device_close;
dev->setLogo = logo_set;
dev->fd = open(DEVICE_NAME, O_RDWR);
if(dev->fd < 0) {
ALOGE("open /dev/logo error");
} else {
ALOGI("open /dev/logo success");
}
*device = &dev->common;
return 0;
}
static struct hw_module_methods_t logo_module_methods =
{
.open = logo_device_open,
};
struct logo_module_t HAL_MODULE_INFO_SYM =
{
.common =
{
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = LOGO_HARDWARE_MODULE_ID,
.name = "LED LOGO CONTROL HW HAL",
.author = "The Android Open Source Project",
.methods = &logo_module_methods,
.dso = NULL,
.reserved = {0,},
},
};
|