跟上一篇的类似,只不过这次我们使用系统定义好的宏来实现。
好吧不多说直接上代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
//下面这些头文件都是gpio中相关宏的定义
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-e.h>
#include <mach/gpio-bank-m.h>
#define DEVICE_NAME "liye_led"
/* 定义幻数 */
#define LED_IOC_MAGIC 'k'
/* 定义命令 */
#define LED_ALLOFF _IO(LED_IOC_MAGIC, 0)
#define LED_ALLON _IO(LED_IOC_MAGIC, 1)
#define LED_SELECTON _IOW(LED_IOC_MAGIC, 2, int)
/*定义命令的最大个数*/
#define LED_IOC_MAXNR 2
static void Led_port_init(void)
{
unsigned tmp;
//gpm0-3 pull up
tmp = readl(S3C64XX_GPMPUD);
tmp &= (~0xFF);
tmp |= 0xaa;
writel(tmp,S3C64XX_GPMPUD);
//gpm0-3 output mode
tmp =readl(S3C64XX_GPMCON);
tmp &= (~0xFFFF);
tmp |= 0x1111;
writel(tmp,S3C64XX_GPMCON);
//gpm0-3 output 0
tmp = readl(S3C64XX_GPMDAT);
tmp &= 0x10;
writel(tmp,S3C64XX_GPMDAT);
}
static void led_all_on(void )
{
unsigned tmp;
tmp = readl(S3C64XX_GPMDAT);
tmp &= 0x10;
writel(tmp,S3C64XX_GPMDAT);
}
static void led_all_off(void)
{
unsigned tmp;
tmp = readl(S3C64XX_GPMDAT);
tmp |= 0x1F;
writel(tmp,S3C64XX_GPMDAT);
}
static void led_select_on(unsigned int led_nu)
{
unsigned tmp;
led_all_off();
tmp = readl(S3C64XX_GPMDAT);
tmp &= ~(led_nu);
writel(tmp,S3C64XX_GPMDAT);
}
static int led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret = 0;
int err = 0;
int ioarg = 0;
/* 检测命令的有效性 */
if (_IOC_TYPE(cmd) != LED_IOC_MAGIC)
return -EINVAL;
if (_IOC_NR(cmd) > LED_IOC_MAXNR)
return -EINVAL;
/* 根据命令类型,检测参数空间是否可以访问 */
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
if (err)
return -EFAULT;
switch (cmd)
{
case LED_ALLOFF://全灭
led_all_off();
break;
case LED_ALLON://全亮
led_all_on();
break;
case LED_SELECTON://根据参数有选择的凉
__get_user(ioarg,(int *)arg);//获得用户空间数据
led_select_on(ioarg);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const struct file_operations led_fops =
{
.owner = THIS_MODULE,
.unlocked_ioctl = led_ioctl,
};
static struct miscdevice led_dev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &led_fops,
};
static int __init led_init(void)
{
int ret;
Led_port_init();//初始化led灯
ret = misc_register(&led_dev);//注册一个混杂设备驱动,主设备号为10
if (ret)
{
printk("misc_register failed\n");
return ret;
}
printk("leds init\n");
return 0;
}
static void __exit led_exit(void)
{
misc_deregister(&led_dev);//注册混杂设备,主设备号为10
printk("leds exit\n");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liye");
module_init(led_init);
module_exit(led_exit);