【注】引脚可能会复用。
1,基础硬件原理:
就是通过配置GPIO(GPH0),把相应的GPIO设置成高电平或者低电平,达到电灯的目的。
2,驱动代码:
#include <linux/fs .h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/module .h>
#include <asm/uaccess .h>
#include <nach/map.h>
#include <rach/ regs-gpio .h>
#include <plat/gpio-cfg.h>
#define DEVICE_ NAME "qt210_ leds"
#define DEVICE_ COUNT 1
#define QT210_ LEDS_ MAJOR 0
#define QT210_ LEDS_ MINOR 234
#define PARAM SIZE 3
static unsigned char mem[4]; //保存4个LEDS的状态
static int major = QT210_LEDS_MAJOR;
static int minor = QT210_LEDS_MINOR;
static dev_t dev_ number; //设备号
static int leds_state = l;
static char *params[] = ("stringl", "string2", "string3");
static int param_size = PARAM_SIZE;
static struct class *leds_class = NULL;
static long qt210_leds_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)
{
switch (cmd)
{
case 0:
case 1:
if (arg » 3)
{
return -EINAL;
if (cmd == 1)
{
gpio_set_ value (55PV210_ _GPH0(arg), 1);
}
else
{
gpio_ set_ value(S5PV210 GPH0(arg), 0);
}
return 0;
default:
return -EINVAL;
}
}
static ssize_t qt210_leds_write(struct file *file, const char _user *buf,size_ t count, loff_t *ppos)
{
unsigned tmp - count;
unsigned long i =0;
memset(mem, e, 4);
if(count>4)
{
tmp = 4;
}
if (copy_from_user(mem, buf, tmp))
{
return -EFAULT;
}
else
{
for(i=0;i<4;i++)
{
if (mem[i] == '1')
{
gpio_set_value(S5PV210_ GPH0(i), 1);
}
else
{
gpio_set_value(S5PV216_ GPH0(i), 0);
}
}
return count;
}
}
static struct file_operations dev_fops =
{
.owner = THIS MODULE,
.unlocked_ioctl = qt210_leds_ioctl,
.write = qt210_leds_write
};
static struct cdev leds_cdev;
//创建设备文件 (/dev/qt210_ leds )
static int leds_create_device(void)
{
int ret = 0;
int err = 0;
//初始化cdev的成员,并建立cdev和file_operations之间的连接
cdev_init(&leds_cdev, &dev_fops);
leds_cdev .owner = THIS_MOOULE;
if (major > 0)
{
//获取设备号和此设备号)
dev_number = MKDEV(major, minor);
err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME);
if (err < 0)
{
printk(KERN_ WIARNING "register. chrdev_ region() failed,n");return err;
return err;
}
else
{
err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT,DEVICE_NAME);
if (err < 0)
{
printk(KERN_WARNING "alloc_chrdev_ region() failed\n");
return err;
}
major = MAJOR(leds_cdev.dev);
minor = MINOR(leds_cdev.dev);
//dev_ number = MKDEV(major, minor);
dev_number = leds_cdev.dev;
}
ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT);
leds_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME);
return ret;
}
static int leds_init_gpm(int leds_default)
{
int err;
int i;
err = gpio_request(S5PV210_GPH0(0), "LED0");
if (err)
{
printk(KERN_ERR "failed to request GPH0(Ѳ) for "" LED0\n");
return err;
}
err = gpio_request(S5PV210_GPH0(1), "LED1");
if (err)
{
printk(KERN_ ERR "failed to request GPH0(1) for " "LED1\n");
return err;
}
err = gpio_request(S5PV210_GPH0(2), "LED2");
if (err)
{
printk(KERN_ERR "failed to request GPH0(2) for " "LED2\n");
return err;
}
err = gpio_request(SSPV210_GPH0(3), “LED3");
if (err)
{
printk(KERN_ERR "failed to request GPH0(3) for " "LED3\n");
return err;
}
for(i=0;i<4;i++)
{
gpio_direction_output(S5PV210_GPH0(i), 1);
gpio_set_value(S5PV210_GPH0(i), leds_default);
return 0;
}
}
// 初始化LED驱动
static int leds_ init(void)
{
int ret;
ret = leds_create_device();
Leds_init_gpm(~leds_state);
printk(DEVICE_NAME"\tinitializedk\n");
printk("param0\t%s\n",params[0]);
printk("paraml\t%s\n",params[1]);
printk("param2\t%s\n",params[2]);
return ret;
}
static void leds_destroy_device(void)
{
device_destroy(leds_class, dev_number);
if (leds_class)
{
class_destroy(leds_class);
}
unregister_chrdev_region(dev_number, DEVICE_COUNT);
return;
}
static void leds_exit(void)
{
int i;
leds_destroy_device();
for(i=0;i<4;i++)
{
gpio_free(S5PV210_GPH0(i));
printk(DEVICE_NAME"texit!\n");
}
}
module_init(leds_init);
module_exit(leds_exit);
module_param(leds_state, int, S_IRUGO|S_IWUSR);
module_param_array(params, charp, ¶m_size, S_IRUGO|S_TWUSR);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HCJ");