⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1.c

📁 一个简单的驱动程序开发框架,可以掌握驱动开发的基本流程.
💻 C
字号:

#include "MyDriver.h"

MODULE_AUTHOR("Chen Xiangpeng");
MODULE_LICENSE("Dual BSD/GPL");
/*--------------------------------------*/
#define MEM_DEV_MAJOR   0
#define MEM_NR_DEVS     1    

//IOW说明是用户向驱动程序写入参数
//IOR说明用户从驱动程序读取参数
#define MEM_IOC_MAGIC     'M'
#define MEM_IOC_SETSIZE   _IO(MEM_IOC_MAGIC, 0)
#define MEM_IOC_PRINT     _IO(MEM_IOC_MAGIC, 1)
#define MEM_IOC_GETOFFSET _IOR(MEM_IOC_MAGIC,2,long)
#define MEM_IOC_MAXNR     3  //这个一定要和上面一致

#define TYPE(dev)   (MINOR(dev) >> 4)  /* high nibble */
#define NUM(dev)    (MINOR(dev) & 0xf) /* low  nibble */

typedef struct{
	long offset;  //offset of the mem file
	long size;    //size of this mem file
	char *base;   //a pointer.
	long usernum; //The use num of this device
	struct semaphore sem;
	devfs_handle_t handle;
}MEM,*MEMP;
/*--------------------------------------*/
static void exit_mem(void);
static int init_mem(void);
int MemInit(MEM *mem);
int MemDestroy(MEM *mem);
int MemPrint(MEM *mem);
int MemSetSize(MEM *mem , long size);
int MemOpen(struct inode *inode, struct file *filp);
int MemRelease(struct inode *inode, struct file *filp);
int MemIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
loff_t MemLlseek(struct file *filp, loff_t off, int whence);
ssize_t MemRead(struct file *filp, char *buf, size_t count,loff_t *f_pos);
ssize_t MemWrite(struct file *filp, const char *buf, size_t count,loff_t *f_pos);
/*--------------------------------------*/
struct file_operations mem_fops={
    llseek:     MemLlseek,
    read:       MemRead,
    write:      MemWrite,
    ioctl:      MemIoctl,
    open:       MemOpen,
    release:    MemRelease,
};
MEMP mem_devs;  //一个指针
devfs_handle_t mem_devfs_dir;
int mem_major   =   MEM_DEV_MAJOR;
int mem_nr_devs =   MEM_NR_DEVS;
static char mem_dev_name[4];
char *device_name = "CXPMEM";
/*--------------------------------------*/
int MemInit(MEM *mem)
{
	mem->offset=0;
	mem->size=0;
	mem->base=NULL;
    sema_init(&(mem->sem), 1);
	mem->usernum=0;
	return 0;
}
/*--------------------------------------*/
int MemDestroy(MEM *mem)
{
	if(mem->base)
	{
		kfree(mem->base);
		mem->base=NULL;
	}
	mem->size=0;
	mem->offset=0;
	return 0;
}
/*--------------------------------------*/
int MemPrint(MEM *mem)
{
	long i;
	printk("\n");
	for(i=0;i<mem->size;i++)
	{
		if(mem->base[i])
			printk("%c",mem->base[i]);
		else
			printk("@");
	}
	printk("\nsize=%ld\n",mem->size);
	printk("offset=%ld\n",mem->offset);
	return 0;
}
/*--------------------------------------*/
int MemSetSize(MEM *mem , long size)
{
	MemDestroy(mem);
	mem->base = kmalloc(size , GFP_KERNEL);
	if(mem->base==NULL)
	{
		printk("can not alloc kernel memory!\n");
		return -2;
	}
	memset(mem->base,0,size);
	mem->size=size;
	mem->offset=0;
	return 0;
}
/*--------------------------------------*/
int MemOpen(struct inode *inode, struct file *filp)
{
	MEMP mem=mem_devs;
	int num=GetDeviceNum(inode);
	int type=GetDeviceType(inode);
	return 0;
}
int MemRelease(struct inode *inode, struct file *filp)
{
	printk("Hello i am closed!\n");
	return 0;
}
ssize_t MemRead(struct file *filp, char *buf, size_t count,loff_t *f_pos)
{
	ssize_t ret=0;
	ssize_t real=0;
	MEMP mem;
	printk("Hi you are reading me!\n");

	if (down_interruptible(&(mem->sem)))
	    return -ERESTARTSYS;

	mem=mem_devs;

	if(mem->offset<0 || mem->offset >= mem->size)
	{
		goto out;
	}
	mem->usernum++;
	if(mem->offset+count > mem->size)
	{
		real = mem->size - mem->offset;
	}
	else
	{
		real = count;
	}
	copy_to_user(buf, mem->base + mem->offset , real);

	printk("%ld bytes read!\n",real);

	mem->offset+=real;
	ret=real;
out:
    up(&mem->sem);
	mem->usernum--;
    return ret;
}
ssize_t MemWrite(struct file *filp, const char *buf, size_t count,loff_t *f_pos)
{
	ssize_t ret=0;
	ssize_t real=0;
	MEMP mem;

	mem=mem_devs;

	if (down_interruptible(&(mem->sem)))
	    return -ERESTARTSYS;

	if(mem->offset<0 || mem->offset >= mem->size)
	{
		goto out;
	}
	mem->usernum++;
	if(mem->offset+count > mem->size)
	{
		real = mem->size - mem->offset;
	}
	else
	{
		real = count;
	}
	copy_from_user(mem->base + mem->offset, buf, real);

	mem->offset+=real;
	ret=real;

out:
    up(&mem->sem);
	mem->usernum--;
    return ret;
}
int MemIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret = 0;
	MEMP mem=mem_devs;

	if (_IOC_TYPE(cmd) != MEM_IOC_MAGIC) return -ENOTTY;
    if (_IOC_NR(cmd) > MEM_IOC_MAXNR) return -ENOTTY;
	if (!CheckUserMemory(cmd, arg))
	{
		printk("Check user memory error!\n");
		return -EFAULT;
	}
	//////////////////////////////////
	if (down_interruptible(&(mem->sem)))
	    return -ERESTARTSYS;

	if(cmd==MEM_IOC_PRINT)
	{
		MemPrint(mem);
		goto out;
	}
	if(cmd==MEM_IOC_SETSIZE)
	{
		MemSetSize(mem,arg);
		goto out;
	}
	if(cmd==MEM_IOC_GETOFFSET)
	{
		__put_user(mem->offset, (long *)arg);
		goto out;
	}

out:
	up(&mem->sem);
	return ret;
}
loff_t MemLlseek(struct file *filp, loff_t off, int whence)
{
	return 0;
}
/*--------------------------------------*/
static int init_mem(void)
{
    int result, i;
	printk("Hello world\n");

	result = register_chrdev(mem_major, device_name, &mem_fops);
    if (result < 0) 
	{
        printk(KERN_WARNING "mem: can't get major %d\n",mem_major);
        return result;
    }
	//如果mem_major为0则动态分配设备号
    if (mem_major == 0) mem_major = result;

	printk("major=%d\n",mem_major);
	//为设备申请内存

    mem_devs = kmalloc(mem_nr_devs * sizeof(MEM), GFP_KERNEL);
    if (!mem_devs) {
        result = -ENOMEM;
        goto fail;
    }

    for (i=0; i < mem_nr_devs; i++) 
	{
		MemInit(mem_devs+i);
	}
	MemSetSize(&mem_devs[0], 256L);
	printk("We are cuccess!!\n");
	return 0;

fail:
    exit_mem();
    return result;
}
/*--------------------------------------*/
static void exit_mem(void)
{
	int i;
	printk(KERN_ALERT "Goodbye world\n");
    unregister_chrdev(mem_major, device_name);

    if (mem_devs)
	{
        for (i=0; i<mem_nr_devs; i++) 
		{
			MemDestroy(mem_devs+i);
        }
        kfree(mem_devs);
    }
}
/*--------------------------------------*/
module_init(init_mem);
module_exit(exit_mem);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -