#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#define ANFANG_LED_GPIO_DR 0x27320000
#define ANFANG_LED_GPIO_DDR 0x2732008
#define ANFANG_LED_GPIO_ADD 0x26042000
struct DEV{
dev_t DEV_num;
struct cdev DEV_cdev;
struct class *DEV_class;
struct device *DEV_device;
int major;
int minor;
char kbuf[32];
unsigned int *xiunidizhi;
};
struct DEV led;
static int led_open(struct inode *inode,struct file *file)
{
file->private_data=container_of(inode->i_cdev,struct DEV,DEV_cdev);
printk("led open\n");
return 0;
}
static ssize_t led_read(struct file *file,char __user *buf,size_t size,loff_t *off)
{
struct DEV *led_data=(struct DEV *)file->private_data;
int ret;
ret=copy_to_user(buf,led_data->kbuf,strlen(led_data->kbuf));
if(ret!=0)
{
printk("read error\n");
}
return 0;
}
static ssize_t led_write(struct file *file,const char __user *buf,size_t size,loff_t *off)
{
struct DEV *led_data=(struct DEV *)file->private_data;
int ret;
ret=copy_from_user(led_data->kbuf,buf,size);
if(ret!=0)
{
printk("read error\n");
}
else
{
printk("kbuf is %d\n",led_data->kbuf[0]);
}
if(led_data->kbuf[0]==1)
{
*(led.xiunidizhi)=0x10001000;
printk("led on\n");
}
else
{
*(led.xiunidizhi)=0x10000000;
printk("led off\n");
}
return 0;
}
static int led_release(struct inode *inode,struct file *file)
{
return 0;
}
struct file_operations led_ops={
.owner=THIS_MODULE,
.open=led_open,
.read=led_read,
.write=led_write,
.release=led_release,
//.unlock_ioctl=;
};
static int moduledev_init(void)
{
int ret;
ret=alloc_chrdev_region(&led.DEV_num,0,1,"anfang_led");
if(ret<0)
{
printk("alloc_chrdev_region error\n");
}
led.major=MAJOR(led.DEV_num);
led.minor=MINOR(led.DEV_num);
printk("major is %d",led.DEV_num);
printk("minor is %d",led.DEV_num);
led.DEV_cdev.owner=THIS_MODULE;
cdev_init(&led.DEV_cdev,&led_ops);
ret=0;
ret=cdev_add(&led.DEV_cdev,led.DEV_num,1);
if(ret<0)
{
printk("cdev_add error\n");
}
led.DEV_class=class_create(THIS_MODULE,"anfang_led_class");
if(IS_ERR(led.DEV_class))
{
printk("class_create error");
}
led.DEV_device=device_create(led.DEV_class,NULL,led.DEV_num,NULL,"anfang_led_device");
if(IS_ERR(led.DEV_device))
{
printk("device_create error");
}
//------------------------------------------创建设备
led.xiunidizhi=ioremap(ANFANG_LED_GPIO_DR,4);
return 0;
}
static void moduledev_exit(void)
{
unregister_chrdev_region(led.DEV_num,1);
cdev_del(&led.DEV_cdev);
device_destroy(led.DEV_class,led.DEV_num);
class_destroy(led.DEV_class);
}
module_init(moduledev_init);
module_exit(moduledev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KFC");
MODULE_VERSION("V1.0");