当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 6 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 谁帮我测个设备驱动程序?
帖子发表于 : 2011-01-21 20:35 

注册: 2010-06-19 11:44
帖子: 679
送出感谢: 2
接收感谢: 1
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 次

页首
 用户资料  
 
2 楼 
 文章标题 : Re: 谁帮我测个设备驱动程序?
帖子发表于 : 2011-01-22 12:20 

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


页首
 用户资料  
 
3 楼 
 文章标题 : Re: 谁帮我测个设备驱动程序?
帖子发表于 : 2011-01-23 18:12 

注册: 2010-06-19 11:44
帖子: 679
送出感谢: 2
接收感谢: 1
自己找到问题所在了,原来我没有在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 =


页首
 用户资料  
 
4 楼 
 文章标题 : Re: 谁帮我测个设备驱动程序?
帖子发表于 : 2011-01-23 18:14 

注册: 2010-06-19 11:44
帖子: 679
送出感谢: 2
接收感谢: 1
生病一年多没碰这驱动代码了,都生疏完了,唉。。。。。。。。。。


页首
 用户资料  
 
5 楼 
 文章标题 : Re: 谁帮我测个设备驱动程序?
帖子发表于 : 2011-01-23 21:39 
头像

注册: 2010-06-09 19:57
帖子: 1211
送出感谢: 2
接收感谢: 9
恭喜身体康复


_________________
听歌


页首
 用户资料  
 
6 楼 
 文章标题 : Re: 谁帮我测个设备驱动程序?
帖子发表于 : 2011-01-23 21:48 

注册: 2010-06-19 11:44
帖子: 679
送出感谢: 2
接收感谢: 1
Ubuntu与Linux 写道:
恭喜身体康复

谢谢


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 6 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 1 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译