#include
#include
//包含有可装载模块需要的大量符合和函数的定义;
#include
//指定初始化和清除函数;
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
/*第二步:添加GPIO寄存器的地址设置(实现GPB5-GPB8的读写)*/
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
#define GPBUP 0x56000018
/*第三步:定义地址变量(针对gpb组寄存器)*/
unsigned long *gpbc;
unsigned long *gpbd;
unsigned long *gpbu;
//定义设备名称
#define DEVICE_NAME "led_dev_dri"
#define BUF_SIZE 1024
static char tmpbuf[BUF_SIZE];
struct class *my_class;
//定义主次设备号
static unsigned int TestMajor=0;
static unsigned int TestMinor=0;
/* 注册字符设备 */
static struct cdev *test_cdev;
static dev_t dev;
static int test_chardev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned int x;
get_user(x, (int *)arg);
//i=cmd;
printk("test-ioctl: param %u %lu\n", cmd, arg);
switch(_IOC_NR(cmd))
{
case 1:
{
printk("The 1 is Press\n");
if(x==0)
{
*gpbd=(*gpbd & (~(0x1<<0x5) ));
printk("fuck you");
}
else
{
*gpbd=((*gpbd &(~(0xf<<5)))|(0x1<<5));
printk("The 1 say goobye!\n");
}
break;
}
case 2:
{
printk("The 2 is Press\n");
if(x==0)
{
*gpbd=(*gpbd & (~(0x1<<0x6) ));
printk("fuck you");
}
else
{
*gpbd=((*gpbd &(~(0xf<<5)))|(0x1<<6));
printk("The 1 say goobye!\n");
}
break;
}
case 3:
{
printk("The 3 is Press\n");
if(x==0)
{
*gpbd=(*gpbd & (~(0x1<<0x7) ));
printk("fuck you");
}
else
{
*gpbd=((*gpbd &(~(0xf<<5)))|(0x1<<7));
printk("The 1 say goobye!\n");
}
break;
}
case 4:
{
printk("The 4 is Press\n");
if(x==0)
{
*gpbd=(*gpbd & (~(0x1<<0x8) ));
printk("fuck you");
}
else
{
*gpbd=((*gpbd &(~(0xf<<5)))|(0x1<<8));
printk("The 1 say goobye!\n");
}
break;
}
default :
printk("error\n");
break;
}
return 0;
}
static int test_chardev_open(struct inode *inode,struct file *file)
{
printk("open major=%d, minor=%d\n", imajor(inode), iminor(inode));
return 0;
}
static int test_chardev_release(struct inode *inode,struct file *file)
{
printk("close major=%d, minor=%d\n", imajor(inode), iminor(inode));
return 0;
}
static ssize_t test_chardev_read(struct file *file,char __user *buf,
size_t const count,loff_t *offset)
{
if(count < BUF_SIZE)
{
if(copy_to_user(buf,tmpbuf,count))
{
printk("copy to user fail \n");
return -EFAULT;
}
}else{
printk("read size must be less than %d\n", BUF_SIZE);
return -EINVAL;
}
*offset += count;
return count;
}
static ssize_t test_chardev_write(struct file *file, const char __user *buf,size_t const count,loff_t *offset)
{
if(count < BUF_SIZE)
{
if(copy_from_user(tmpbuf,buf,count))
{
printk("copy from user fail \n");
return -EFAULT;
}
}else{
printk("size must be less than %d\n", BUF_SIZE);
return -EINVAL;
}
*gpbd=(*gpbd & ~(0xF<<0x5) )|(tmpbuf[0]);
*offset += count;
return count;
}
static struct file_operations chardev_fops={
.owner = THIS_MODULE,
.read = test_chardev_read,
.write = test_chardev_write,
.open = test_chardev_open,
.ioctl =test_chardev_ioctl,
.release = test_chardev_release,
};
static int __init test_init(void) //设备探测接口
{
int result;
/*分配设备编号*/
printk(" go to my_dev probe \n");
if(TestMajor)
{
dev=MKDEV(TestMajor,TestMinor);//创建设备编号
result=register_chrdev_region(dev,1,DEVICE_NAME);
} else {
result=alloc_chrdev_region(&dev,TestMinor,1,DEVICE_NAME);
TestMajor=MAJOR(dev);
}
if(result<0)
{
printk(KERN_WARNING"LED: cannot get major %d \n",TestMajor);
return result;
}
/* 注册字符设备 */
test_cdev=cdev_alloc();
cdev_init(test_cdev,&chardev_fops);
test_cdev->owner=THIS_MODULE;
result=cdev_add(test_cdev,dev,1);
if(result)
printk("<1>Error %d while register led device!\n",result);
/* create your own class under /sysfs */
// my_class = class_create(THIS_MODULE, "my_class");
/* register your own device in sysfs, and this will cause udev to create corresponding device node */
// device_create( my_class, NULL, dev,NULL,DEVICE_NAME);
/*第五步 完成IO内存的申请及映射*/
/*IO内存申请*/
request_mem_region(GPBCON,4,"GPBC");
request_mem_region(GPBDAT,4,"GPBD");
request_mem_region(GPBUP,4,"GPBU");
/*IO内存映射*/
gpbc= ioremap_nocache(GPBCON,4);
gpbd = ioremap_nocache(GPBDAT,4);
gpbu = ioremap_nocache(GPBUP,4);
/*对映射后的IO内存进行位操作*/
*gpbc=(*gpbc & (~(0xFF<<10))) | (0x55<<10); //配置GPB5-8为输出
*gpbd=(*gpbd & (~(0xF<<5))) | (0xF<<5); //配置GPB5-8输出 1
*gpbu=(*gpbu & (~(0xF<<5))) | (0xF<<5); //配置GPB5-8 上拉电阻禁止
return 0;
}
static void __exit test_exit(void)
{
printk("Goodbye world 1.\n");
unregister_chrdev_region(MKDEV(TestMajor,TestMinor),1);
cdev_del(test_cdev);
/*IO内存释放*/
release_mem_region(GPBCON,4);
release_mem_region(GPBDAT,4);
release_mem_region(GPBUP,4);
/*IO内存解除映射*/
iounmap(gpbc);
iounmap(gpbd);
iounmap(gpbu);
}
/*
static void __devexit my_remove(void) //设备移除接口
{
unregister_chrdev_region(MKDEV(TestMajor,TestMinor),1);
device_destroy(my_class, MKDEV(TestMajor, 0)); //delete device node under /dev
class_destroy(my_class); //delete class created by us
cdev_del(test_cdev);
printk(" goodbye my_dev probe \n");
}
struct platform_device my_dev = {
.name= "my_dev",
.id= -1,
};
EXPORT_SYMBOL(my_dev); //声明一个内核的全局符号my_dev;
static struct platform_driver my_driver = {
.probe = my_probe, //驱动探测
.remove = __devexit_p(my_remove), //驱动移除
.driver = {
.name ="my_dev",
.owner = THIS_MODULE,
},
};
EXPORT_SYMBOL(my_driver); //声明一个内核的全局符号my_driver;
static int __init my_init(void)
{
printk(" go to my_dev probe init \n");
return platform_driver_register(&my_driver ); //平台设备注册
}
static void __exit my_cleanup(void)
{
printk(" goodbye my_dev probe cleanup \n");
platform_driver_unregister(&my_driver ); //平台设备注销
}
*/
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");