谁帮我测个设备驱动程序?

内核编译和嵌入式产品的设计与开发
回复
天使ッ翼
帖子: 679
注册时间: 2010-06-19 11:44

谁帮我测个设备驱动程序?

#1

帖子 天使ッ翼 » 2011-01-21 20:35

RT
这代码我写挺久了,今天拿来测试不成功
当然以前写的时候测试是成功的,不过是在我同学的笔记本上编写和测试的
现在回到家是用家里的电脑测试,ubuntu是8.04的
谁帮我测试下有什么问题,谢谢了

mydev.c

代码: 全选

/***************************************************************************
 *	mydev.c
 *    -------------------
 *	版本号		: v1.0
 *	原始作者	:  天使之翼
 *	创建时间	: 2009-8-16
 *	文件说明	: 设备驱动的处理程序
 *	实现功能	: 设备驱动的加载,卸载,打开,释放,读写,控制,定位
 *	修改列表	: 
 *	
 ***************************************************************************/


#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#define BUF_SIZE   0x1000		//缓冲区大小
#define CLEAR_BUF  0x1       	//清空缓冲区
#define MYDEV_NAME "mydev"		//设备名
#define MYDEV_MAJOR  2011		//主设备号

static int mydev_major = MYDEV_MAJOR;

//自定义的设备结构体
typedef struct mydev
{
	struct cdev cdev;
	unsigned char buf[BUF_SIZE];
}MYDEV;

MYDEV *p_mydev;


/***************************************************************************
功能:	打开设备
参数:	设备节点指针, 设备文件结构体指针
返回值:	0   成功
		非0  失败
***************************************************************************/
int mydev_open(struct inode *inode, struct file *filp)
{
	filp->private_data = p_mydev;  //将自定义设备结构体指针赋给文件私有数据指针
	return 0;
}



/***************************************************************************
功能:	释放设备
参数:	设备节点指针, 设备文件结构体指针
返回值:	0   成功
		非0  失败
***************************************************************************/
int mydev_release(struct inode *inode, struct file *filp)
{
	return 0;
}



/***************************************************************************
功能:	控制设备
参数:	设备节点指针, 设备文件结构体指针, 控制命令, 用户空间传递的自定义的数据
返回值:	0   成功
		非0  失败
***************************************************************************/
static int mydev_ioctl(struct inode *inode, struct file *filp, 
					   unsigned int cmd, unsigned long arg)
{
	MYDEV *p_mydev = filp->private_data;

	switch(cmd)
	{
		case CLEAR_BUF:
			memset(p_mydev->buf, 0, BUF_SIZE);
			printk(KERN_INFO "buf is set to zero\n");
			break;
		
		default:
			return -EINVAL;
	}
	
	return 0;
}



/***************************************************************************
功能:	读设备
参数:	设备文件结构体指针, 用户空间传递的缓冲区指针, 读取的字节数, 当前读写位置
返回值:	读取的字节数  成功
		错误值 		失败
***************************************************************************/
static ssize_t mydev_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
	unsigned long p = *ppos;
	unsigned int count = size;
	int ret = 0;
	MYDEV *p_mydev = filp->private_data;

	if(p >= BUF_SIZE)
	{
		return count ? -ENXIO : 0;
	}

	if(count > BUF_SIZE - p)
	{
		count = BUF_SIZE - p;
	}

	if(copy_to_user(buf, (void *)(p_mydev->buf + p), count))
	{
		ret = -EFAULT;
	}
	else
	{
		*ppos += count;
		ret = count;
		printk(KERN_INFO "read %d bytes(s) from %ld\n", count, p);
	}

	return ret;
}



/***************************************************************************
功能:	写设备
参数:	设备文件结构体指针, 用户空间传递的缓冲区指针, 写入的字节数, 当前读写位置
返回值:	写入的字节数  成功
		错误值 		失败
***************************************************************************/
static ssize_t mydev_write(struct file *filp, const char __user *buf, 
						   size_t size, loff_t *ppos)
{
	unsigned long p = *ppos;
	unsigned int count = size;
	int ret = 0;
	MYDEV *p_mydev = filp->private_data;

	if(p >= BUF_SIZE)
	{
		return count ? -ENXIO : 0;
	}

	if(count > BUF_SIZE - p)
	{
		count = BUF_SIZE - p;
	}

	if(copy_from_user(p_mydev->buf + p, buf, count))
	{
		ret = -EFAULT;
	}
	else
	{
		*ppos += count;
		ret = count;
		printk(KERN_INFO "written %d bytes(s) from %ld\n", count , p);
	}

	return ret;
}



/***************************************************************************
功能:	定位
参数:	设备文件结构体指针, 偏移量, 何处移动
返回值:	当前读写位置  成功
		错误值	   失败
***************************************************************************/
static loff_t mydev_llseek(struct file *filp, loff_t offset, int whence)
{
	loff_t ret = 0;

	switch(whence)
	{
		case 0:
			if(offset < 0)
			{
				ret = -EINVAL;
				break;
			}
			
			if((unsigned int)offset > BUF_SIZE)
			{
				ret = -EINVAL;
				break;
			}

			filp->f_pos = (unsigned int)offset;
			ret = filp->f_pos;
			break;
		
		case 1:
			if((filp->f_pos + offset) > BUF_SIZE)
			{
				ret = -EINVAL;
				break;
			}

			if((filp->f_pos + offset) < 0)
			{
				ret = -EINVAL;
				break;
			}
			
			filp->f_pos += offset;
			ret = filp->f_pos;
			break;
	}

	return ret;
}


//文件操作结构体
static struct file_operations mydev_fops = 
{
	.owner      = THIS_MODULE,
	.open       = mydev_open,
	.release    = mydev_release,
	.read 		= mydev_read,
	.write		= mydev_write,
	.ioctl 		= mydev_ioctl,
	.llseek		= mydev_llseek,
};



/***************************************************************************
功能:	初始化并注册cdev
参数:	自定义的设备结构体指针, 次设备号
返回值:	无
***************************************************************************/
static void mydev_setup_cdev(MYDEV *p_mydev, int index)
{
	dev_t devno;
	int errno;

	devno = MKDEV(mydev_major, index);
	cdev_init(&p_mydev->cdev, &mydev_fops);
	p_mydev->cdev.owner = THIS_MODULE;
	p_mydev->cdev.ops = &mydev_fops;
	
	errno = cdev_add(&p_mydev->cdev, devno, 1);  //注册cdev
	if(errno)
	{
		printk(KERN_INFO "Error %d adding LED %d\n", errno, index);
	}
}



/***************************************************************************
功能:	加载设备驱动模块
参数:	无
返回值:	0   成功
		非0  失败
***************************************************************************/
int mydev_init(void)
{
	int ret;
	dev_t devno;
	
	devno = MKDEV(mydev_major, 0);
	if(mydev_major)
	{
		ret = register_chrdev_region(devno, 1, MYDEV_NAME);  //申请设备号
	}
	else
	{
		ret = alloc_chrdev_region(&devno, 0, 1, MYDEV_NAME);  //动态申请设备号
		mydev_major = MAJOR(devno);
	}

	if(ret < 0)
	{
		return ret;
	}

	p_mydev = kmalloc(sizeof(MYDEV), GFP_KERNEL);
	if(!p_mydev)
	{
		ret = -ENOMEM;
		goto fail_malloc;
	}
	memset(p_mydev, 0, sizeof(MYDEV));
	
	mydev_setup_cdev(p_mydev, 0);
	return 0;

	fail_malloc:
	unregister_chrdev_region(devno, 1);
	return ret;
}



/***************************************************************************
功能:	卸载设备驱动模块
参数:	无
返回值:	无
***************************************************************************/
void mydev_exit(void)
{
	cdev_del(&p_mydev->cdev);  //注销cdev
	kfree(p_mydev);  //释放自定义设备结构体
	unregister_chrdev_region(MKDEV(mydev_major, 0), 1);  //释放设备号
}


module_init(mydev_init);
module_exit(mydev_exit);

MODULE_AUTHOR("Xie HoneYong");
MODULE_LICENSE("Dual BSD/GPL");
main.c

代码: 全选

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

#define CLEAR_BUF  0x1  //清空缓冲区
#define DEVICE_FILENAME "/dev/mydev"

int main(void)
{
	int handle;
	char buf[128] = "Hello World!";

	handle = open(DEVICE_FILENAME, O_RDWR | O_NDELAY);
	printf("handle = %d\n", handle);
	if(handle < 0)
	{
		printf("open mydev device failure!\n");
	}
	else
	{
		printf("open mydev device successful!\n");
		printf("buf = %s\n", buf);
		write(handle, buf, sizeof(buf));

		memset(buf, 0, sizeof(buf));
		lseek(handle, 0, SEEK_SET);
		read(handle, buf, sizeof(buf));
		printf("buf = %s\n", buf);

		ioctl(handle, CLEAR_BUF, 0);
		lseek(handle, 0, SEEK_SET);
		memset(buf, 0, sizeof(buf));
		read(handle, buf, sizeof(buf));
		printf("buf = %s\n", buf);
	}

	return 0;
}
makefile

代码: 全选

obj-m := mydev.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
	rm -rf *.ko
	rm -rf *.mod.*
	rm -rf .*.cmd
	rm -rf *.o
	rm *~
上次由 天使ッ翼 在 2011-01-23 21:47,总共编辑 4 次。
天使ッ翼
帖子: 679
注册时间: 2010-06-19 11:44

Re: 谁帮我测个设备驱动程序?

#2

帖子 天使ッ翼 » 2011-01-22 12:20

编译是成功的
插入模块也是成功的
可是去dev目录下看却没有我注册的设备
真是奇了怪了
高手帮帮忙啊
代码应该是没问题的
不知道哪里出错了
天使ッ翼
帖子: 679
注册时间: 2010-06-19 11:44

Re: 谁帮我测个设备驱动程序?

#3

帖子 天使ッ翼 » 2011-01-23 18:12

自己找到问题所在了,原来我没有在dev目录下创建mydev设备节点
导致我调用测试失败

具体到编译运行方法如下:
创建设备节点:
sudo mknod /dev/mydev c 2011 0

编译:
make
gcc main.c -o main

插入模块:
sudo insmod mydev.ko

删除模块:
sudo rmmod mydev.ko

查看模块:
lsmod

测试:
sudo ./main

查看内核输出:
dmesg

成功到话会在shell下看到:
handle = 3
open mydev device successful!
buf = Hello World!
buf = Hello World!
buf =
天使ッ翼
帖子: 679
注册时间: 2010-06-19 11:44

Re: 谁帮我测个设备驱动程序?

#4

帖子 天使ッ翼 » 2011-01-23 18:14

生病一年多没碰这驱动代码了,都生疏完了,唉。。。。。。。。。。
头像
Ubuntu与Linux
帖子: 1211
注册时间: 2010-06-09 19:57

Re: 谁帮我测个设备驱动程序?

#5

帖子 Ubuntu与Linux » 2011-01-23 21:39

恭喜身体康复
天使ッ翼
帖子: 679
注册时间: 2010-06-19 11:44

Re: 谁帮我测个设备驱动程序?

#6

帖子 天使ッ翼 » 2011-01-23 21:48

Ubuntu与Linux 写了:恭喜身体康复
谢谢
回复