diff --git a/Linux/KernelDriver/3.2/Char/demo_char.c b/Linux/KernelDriver/3.2/Char/demo_char.c index 5890320..8d3361c 100644 --- a/Linux/KernelDriver/3.2/Char/demo_char.c +++ b/Linux/KernelDriver/3.2/Char/demo_char.c @@ -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; iprivate_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