linux驱动开发扩展--新接口使用例程

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <mach/gpio-bank.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/device.h>

//物理地址
#define GPJ0CON		0xE0200240
#define GPJ0DAT		0xE0200244

//虚拟地址
#define rGPJ0CON	*((volatile unsigned int *)S5PV210_GPJ0CON)
#define rGPJ0DAT	*((volatile unsigned int *)S5PV210_GPJ0DAT)

static dev_t devnb;
char kbuf[10]="987654321";
static struct cdev mdev,*pdev;
static struct class *test_class;

volatile unsigned int *pGPJ0CON,*pGPJ0DAT;

static int test_open(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_open\n");
	//led on
	//rGPJ0CON = 0x11111111;
        //rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
	*pGPJ0CON = 0x11111111;
	*pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));		// 亮
	return 0;
}

static int test_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_release\n");
	//led off
	//rGPJ0CON = 0x11111111;
        //rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
	*pGPJ0CON = 0x11111111;
        *pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));         // 亮
	return 0;
}

static ssize_t test_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
	int ret=-1;
	
	printk(KERN_INFO "test_chrdev_read\n");
	ret=copy_to_user(buf,kbuf,10);
	if(ret)
	{
		printk(KERN_ERR "copy_to_user error, ret = %d.\n", ret);
		return ret;
	}
	printk(KERN_INFO "copy_to_user ok, ret = %d.\n", ret);

	return 0;
}

static ssize_t test_write(struct file *file, const char __user *buf,size_t siz, loff_t *ppos)
{
	int ret=-1;
	
	printk(KERN_INFO "test_chrdev_write\n");
	memset(kbuf, 0, 10);
	ret=copy_from_user(kbuf,buf,10);
	if(ret)
	{
		printk(KERN_ERR "copy_from_user error, ret = %d.\n", ret);
		return ret;
	}
	printk(KERN_INFO "copy_from_user ok, ret = %d.\n", ret);
	printk(KERN_INFO "buf = %s.\n", kbuf);

	return 0;
}

static const struct file_operations test_fops = {
	.owner		= THIS_MODULE,
	.open           = test_open,
	.release        = test_release,
	.read           = test_read,
	.write          = test_write,
};

// 模块安装函数
static int __init chrdev_init(void)
{	
	int ret=-1;

	printk(KERN_INFO "chrdev_init helloworld init\n");
	//printk("<7>" "chrdev_init helloworld init\n");
	//printk("<7> chrdev_init helloworld init\n");
	
	//申请设备号
	/*自己定义设备号*/
#if 0
	devnb=MKDEV(250,12);
	ret=register_chrdev_region(devnb,1,"test-dev");
	if (ret < 0)
		printk(KERN_WARNING "test: could not get major number\n");
#endif
	/*内核分配设备号*/
	ret = alloc_chrdev_region(&devnb, 12, 1, "test-dev");
	if (ret < 0)
		printk(KERN_ERR "%s: failed to allocate char dev region\n",__FILE__);
	printk(KERN_INFO "test: get major number done!\n");
        printk(KERN_INFO "MA: %d  MI: %d  \n",MAJOR(devnb),MINOR(devnb));
	//注册字符设备驱动
	pdev = cdev_alloc();
	//cdev_init(&mdev, &test_fops);
	cdev_init(pdev, &test_fops);
	//ret = cdev_add(&mdev, devnb, 1);
	ret = cdev_add(pdev, devnb, 1);
	if (ret) {
		printk(KERN_ERR "Unable to cdev_add\n");
		return -EINVAL;
	}
	printk(KERN_INFO "cdev_add success\n");
	//申请动态映射所需内存资源
        if (!request_mem_region(GPJ0CON, 4,"GPJ0CON,"))
                return -EBUSY;
        if (!request_mem_region(GPJ0DAT, 4, "GPJ0DAT"))
                return -EINVAL;
        //建立动态映射
        pGPJ0CON = ioremap(GPJ0CON, 4);
        pGPJ0DAT = ioremap(GPJ0DAT, 4);
	
	//自动创建设备文件
	test_class = class_create(THIS_MODULE, "test");
	if (IS_ERR(test_class)) 
	{
		printk(KERN_ERR "test: failed to create class");
		return -EINVAL;
	}
	device_create(test_class, NULL, devnb, NULL, "test");

	return 0;
}

// 模块下载函数
static void __exit chrdev_exit(void)
{
	printk(KERN_INFO "chrdev_exit helloworld exit\n");

	//销毁动态映射
        iounmap(pGPJ0CON);
        iounmap(pGPJ0DAT);
        //释放动态映射资源
        release_mem_region(GPJ0CON, 4);
        release_mem_region(GPJ0DAT, 4);
	//注销字符设备驱动并释放设备号
	//cdev_del(&mdev);
	cdev_del(pdev);
	unregister_chrdev_region(devnb, 1);

	//自动删除设备文件
	device_destroy(test_class, devnb);
	class_destroy(test_class);
}


module_init(chrdev_init);
module_exit(chrdev_exit);

// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值