为读操作增加测试代码.Signed-off-by: ithink.chan <chenyang@autoai.com>
This commit is contained in:
parent
9ac7295276
commit
ca1c3a6a63
|
@ -34,12 +34,17 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
#define DEMO_DEV_CNT 2
|
||||
|
||||
// This is a test.
|
||||
#define DEMO_DATA_SIZE 5
|
||||
|
||||
static int demo_major = 0;
|
||||
|
||||
struct demo_dev
|
||||
{
|
||||
struct cdev cdev;
|
||||
struct device *dev;
|
||||
// This is a test.
|
||||
char demo_text[DEMO_DATA_SIZE];
|
||||
};
|
||||
|
||||
struct class *class;
|
||||
|
@ -62,21 +67,72 @@ static int demo_release(struct inode *inode, struct file* filp)
|
|||
static loff_t demo_llseek(struct file *filp, loff_t offset, int origin)
|
||||
{
|
||||
struct demo_dev *devp = filp->private_data;
|
||||
loff_t ret;
|
||||
|
||||
(void)devp;
|
||||
// This is a test.
|
||||
switch(origin)
|
||||
{
|
||||
case 0: // 从文件开头开始偏移
|
||||
if(offset<0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if((unsigned int)offset>DEMO_DATA_SIZE)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
filp->f_pos = (unsigned int)offset;
|
||||
ret = filp->f_pos;
|
||||
break;
|
||||
case 1: // 从当前位置开始偏移
|
||||
if((filp->f_pos+offset)>DEMO_DATA_SIZE)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if((filp->f_pos+offset)<0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
filp->f_pos += offset;
|
||||
ret = filp->f_pos;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return filp->f_pos;
|
||||
}
|
||||
|
||||
static ssize_t demo_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset)
|
||||
static ssize_t demo_read(struct file *filp, char __user *buffer, size_t count, loff_t *position)
|
||||
{
|
||||
struct demo_dev *devp = filp->private_data;
|
||||
const char __user *p = buffer;
|
||||
loff_t p = *position;
|
||||
ssize_t ret = 0;
|
||||
|
||||
(void)devp;
|
||||
return p-buffer;
|
||||
// This is a test.
|
||||
// 分析和获取有效的读长度
|
||||
if(DEMO_DATA_SIZE<=p) // 要读的偏移位置越界
|
||||
return 0; // End of a file
|
||||
if(DEMO_DATA_SIZE<(count+p)) // 要读的字节数太大
|
||||
count = DEMO_DATA_SIZE-p;
|
||||
|
||||
if(copy_to_user((void*)buffer, &devp->demo_text[p], count))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
{
|
||||
*position += count;
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t demo_write(struct file *filp, const char __user *buffer, size_t count, loff_t *offset)
|
||||
static ssize_t demo_write(struct file *filp, const char __user *buffer, size_t count, loff_t *position)
|
||||
{
|
||||
struct demo_dev *devp = filp->private_data;
|
||||
const char __user *p = buffer;
|
||||
|
@ -162,14 +218,19 @@ static int demo_setup_cdev(struct demo_dev *devp, int index)
|
|||
err = cdev_add(&devp->cdev, devno, 1);
|
||||
if(err)
|
||||
{
|
||||
printk(KERN_ERR "Error(%d) %d.\r\n", index, err);
|
||||
printk(KERN_ERR "demo add cdev:%d error:%d.\r\n", index, err);
|
||||
goto out_cdev;
|
||||
}
|
||||
|
||||
// 创建设备节点
|
||||
memset(name, 0, 16);
|
||||
sprintf(name, DEMO_MODULE_NAME"%d", index);
|
||||
printk(KERN_INFO "New dev name:%s", name);
|
||||
printk(KERN_INFO "demo new dev name:%s", name);
|
||||
devp->dev = device_create(class, NULL, devp->cdev.dev, NULL, name);
|
||||
// This is a test.
|
||||
devp->demo_text[DEMO_DATA_SIZE-2] = '\n';
|
||||
devp->demo_text[DEMO_DATA_SIZE-1] = 0;
|
||||
sprintf(devp->demo_text, "%d", index);
|
||||
return 0;
|
||||
out_cdev:
|
||||
cdev_del(&devp->cdev);
|
||||
|
@ -182,9 +243,9 @@ static int __init demo_init(void)
|
|||
int err, i;
|
||||
dev_t devno = MKDEV(demo_major, 0);
|
||||
|
||||
if(demo_major)
|
||||
if(demo_major) // 使用固定主设备号
|
||||
err = register_chrdev_region(devno, DEMO_DEV_CNT, DEMO_MODULE_NAME);
|
||||
else
|
||||
else // 动态分配主设备号
|
||||
{
|
||||
err = alloc_chrdev_region(&devno, 0, DEMO_DEV_CNT, DEMO_MODULE_NAME);
|
||||
demo_major = MAJOR(devno);
|
||||
|
@ -200,6 +261,7 @@ static int __init demo_init(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
// 创建设备类, 子设备属于同一个设备类
|
||||
class = class_create(THIS_MODULE, DEMO_MODULE_NAME);
|
||||
for(i=0; i<DEMO_DEV_CNT; i++)
|
||||
{
|
||||
|
@ -235,6 +297,7 @@ static void __exit demo_exit(void)
|
|||
unregister_chrdev_region(MKDEV(demo_major, 0), DEMO_DEV_CNT);
|
||||
}
|
||||
|
||||
// insmod 时可传入参数
|
||||
module_param(demo_major, int, S_IRUGO);
|
||||
|
||||
module_init(demo_init);
|
||||
|
|
|
@ -34,12 +34,17 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
#define DEMO_DEV_CNT 2
|
||||
|
||||
// This is a test.
|
||||
#define DEMO_DATA_SIZE 5
|
||||
|
||||
static int demo_major = 0;
|
||||
|
||||
struct demo_dev
|
||||
{
|
||||
struct cdev cdev;
|
||||
struct device *dev;
|
||||
// This is a test.
|
||||
char demo_text[DEMO_DATA_SIZE];
|
||||
};
|
||||
|
||||
struct class *class;
|
||||
|
@ -62,21 +67,72 @@ static int demo_release(struct inode *inode, struct file* filp)
|
|||
static loff_t demo_llseek(struct file *filp, loff_t offset, int origin)
|
||||
{
|
||||
struct demo_dev *devp = filp->private_data;
|
||||
loff_t ret;
|
||||
|
||||
(void)devp;
|
||||
// This is a test.
|
||||
switch(origin)
|
||||
{
|
||||
case 0: // 从文件开头开始偏移
|
||||
if(offset<0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if((unsigned int)offset>DEMO_DATA_SIZE)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
filp->f_pos = (unsigned int)offset;
|
||||
ret = filp->f_pos;
|
||||
break;
|
||||
case 1: // 从当前位置开始偏移
|
||||
if((filp->f_pos+offset)>DEMO_DATA_SIZE)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if((filp->f_pos+offset)<0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
filp->f_pos += offset;
|
||||
ret = filp->f_pos;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return filp->f_pos;
|
||||
}
|
||||
|
||||
static ssize_t demo_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset)
|
||||
static ssize_t demo_read(struct file *filp, char __user *buffer, size_t count, loff_t *position)
|
||||
{
|
||||
struct demo_dev *devp = filp->private_data;
|
||||
const char __user *p = buffer;
|
||||
loff_t p = *position;
|
||||
ssize_t ret = 0;
|
||||
|
||||
(void)devp;
|
||||
return p-buffer;
|
||||
// This is a test.
|
||||
// 分析和获取有效的读长度
|
||||
if(DEMO_DATA_SIZE<=p) // 要读的偏移位置越界
|
||||
return 0; // End of a file
|
||||
if(DEMO_DATA_SIZE<(count+p)) // 要读的字节数太大
|
||||
count = DEMO_DATA_SIZE-p;
|
||||
|
||||
if(copy_to_user((void*)buffer, &devp->demo_text[p], count))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
{
|
||||
*position += count;
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t demo_write(struct file *filp, const char __user *buffer, size_t count, loff_t *offset)
|
||||
static ssize_t demo_write(struct file *filp, const char __user *buffer, size_t count, loff_t *position)
|
||||
{
|
||||
struct demo_dev *devp = filp->private_data;
|
||||
const char __user *p = buffer;
|
||||
|
@ -162,14 +218,19 @@ static int demo_setup_cdev(struct demo_dev *devp, int index)
|
|||
err = cdev_add(&devp->cdev, devno, 1);
|
||||
if(err)
|
||||
{
|
||||
printk(KERN_ERR "Error(%d) %d.\r\n", index, err);
|
||||
printk(KERN_ERR "demo add cdev:%d error:%d.\r\n", index, err);
|
||||
goto out_cdev;
|
||||
}
|
||||
|
||||
// 创建设备节点
|
||||
memset(name, 0, 16);
|
||||
sprintf(name, DEMO_MODULE_NAME"%d", index);
|
||||
printk(KERN_INFO "New dev name:%s", name);
|
||||
printk(KERN_INFO "demo new dev name:%s", name);
|
||||
devp->dev = device_create(class, NULL, devp->cdev.dev, NULL, name);
|
||||
// This is a test.
|
||||
devp->demo_text[DEMO_DATA_SIZE-2] = '\n';
|
||||
devp->demo_text[DEMO_DATA_SIZE-1] = 0;
|
||||
sprintf(devp->demo_text, "%d", index);
|
||||
return 0;
|
||||
out_cdev:
|
||||
cdev_del(&devp->cdev);
|
||||
|
@ -182,9 +243,9 @@ static int __init demo_init(void)
|
|||
int err, i;
|
||||
dev_t devno = MKDEV(demo_major, 0);
|
||||
|
||||
if(demo_major)
|
||||
if(demo_major) // 使用固定主设备号
|
||||
err = register_chrdev_region(devno, DEMO_DEV_CNT, DEMO_MODULE_NAME);
|
||||
else
|
||||
else // 动态分配主设备号
|
||||
{
|
||||
err = alloc_chrdev_region(&devno, 0, DEMO_DEV_CNT, DEMO_MODULE_NAME);
|
||||
demo_major = MAJOR(devno);
|
||||
|
@ -200,6 +261,7 @@ static int __init demo_init(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
// 创建设备类, 子设备属于同一个设备类
|
||||
class = class_create(THIS_MODULE, DEMO_MODULE_NAME);
|
||||
for(i=0; i<DEMO_DEV_CNT; i++)
|
||||
{
|
||||
|
@ -235,6 +297,7 @@ static void __exit demo_exit(void)
|
|||
unregister_chrdev_region(MKDEV(demo_major, 0), DEMO_DEV_CNT);
|
||||
}
|
||||
|
||||
// insmod 时可传入参数
|
||||
module_param(demo_major, int, S_IRUGO);
|
||||
|
||||
module_init(demo_init);
|
||||
|
|
Loading…
Reference in New Issue