这里为了方便调试和移植,统一采用mod的形式注册设备和驱动
实际应用应该注意在平台中编译进内核,而非.ko文件的模块加载
首先我们要先在总线上注册一个设备
下面贴用模块注册设备的代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("HQU_Orange");
#define DEVICE_NAME "Hello_device"
void Hello_device_release(struct device *dev);
struct platform_device Hello_device =
{
.name = DEVICE_NAME ,
.id = -1 ,
.dev =
{
.release= Hello_device_release ,
}
};
static int Mini_Linux_Device_Module_Init (void)
{
int Device_Status;
printk(KERN_EMERG "Mini Liunx Device Module Enter ! \r\n");
Device_Status=platform_device_register(&Hello_device);
printk(KERN_EMERG "Mini Linux Device Status is %d \n",Device_Status);
return 0;
}
static void Mini_Linux_Device_Module_Exit (void)
{
platform_device_unregister(&Hello_device);
printk(KERN_EMERG "Mini Linux Device Module Exit ! \r\n");
}
void Hello_device_release(struct device *dev)
{
printk(KERN_EMERG DEVICE_NAME "\tdevice release wolk!\r\n");
}
module_init(Mini_Linux_Device_Module_Init);
module_exit(Mini_Linux_Device_Module_Exit);
这个设备的名字是
将设备注册到platform上
将设备从platfrom上卸载
我现在将它划分为杂项设备,并且编写驱动代码
下面贴设备的驱动代码
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("HQU_Orange");
#define DEVICE_NAME "Hello_device"
#define DEVICENODE_NAME "Hello"
int Hello_driver_probe(struct platform_device* Hello_device);
int Hello_driver_remove(struct platform_device* Hello_device);
void Hello_driver_shutdown(struct platform_device* Hello_device);
int Hello_driver_suspend(struct platform_device* Hello_device,pm_message_t state);
int Hello_driver_resume(struct platform_device* Hello_device);
int Hello_driver_fops_open(struct inode* p_inode,struct file* p_file);
int Hello_driver_fops_release(struct inode* p_inode,struct file* p_file);
long Hello_driver_fops_unlocked_ioctl(struct file* p_file ,unsigned int ID ,unsigned long cmd);
struct platform_driver Hello_driver =
{
.probe = Hello_driver_probe ,
.remove = Hello_driver_remove ,
.shutdown= Hello_driver_shutdown ,
.suspend= Hello_driver_suspend ,
.resume = Hello_driver_resume ,
.driver =
{
.name = DEVICE_NAME ,
.owner = THIS_MODULE ,
}
};
struct file_operations Hello_driver_fops =
{
.owner = THIS_MODULE ,
.open = Hello_driver_fops_open ,
.release = Hello_driver_fops_release ,
.unlocked_ioctl = Hello_driver_fops_unlocked_ioctl,
};
struct miscdevice Hello_misc_device=
{
.minor = MISC_DYNAMIC_MINOR ,
.name = DEVICENODE_NAME ,
.fops = &Hello_driver_fops ,
};
static int Mini_Linux_Driver_Init (void)
{
int Driver_Status;
printk(KERN_EMERG "Mini Liunx Driver Enter ! \r\n");
Driver_Status=platform_driver_register(&Hello_driver);
printk(KERN_EMERG "Mini Linux Driver Status is %d \n",Driver_Status);
return 0;
}
static void Mini_Linux_Driver_Exit (void)
{
platform_driver_unregister(&Hello_driver);
printk(KERN_EMERG "Mini Linux Driver Exit ! \r\n");
}
int Hello_driver_probe(struct platform_device* Hello_device)
{
printk(KERN_EMERG "device-> name = %s device -> id = %d probe !\r\n",Hello_device->name,Hello_device->id);
misc_register(&Hello_misc_device);
return 0;
}
int Hello_driver_remove(struct platform_device* Hello_device)
{
printk(KERN_EMERG "device-> name = %s device -> id = %d remove!\r\n",Hello_device->name,Hello_device->id);
misc_deregister(&Hello_misc_device);
return 0;
}
void Hello_driver_shutdown(struct platform_device* Hello_device)
{
printk(KERN_EMERG "device-> name = %s device -> id = %d shutdown!\r\n",Hello_device->name,Hello_device->id);
}
int Hello_driver_suspend(struct platform_device* Hello_device,pm_message_t state)
{
printk(KERN_EMERG "device-> name = %s device -> id = %d suspend!\r\n",Hello_device->name,Hello_device->id);
return 0;
}
int Hello_driver_resume(struct platform_device* Hello_device)
{
printk(KERN_EMERG "device-> name = %s device -> id = %d resume!\r\n",Hello_device->name,Hello_device->id);
return 0;
}
int Hello_driver_fops_open(struct inode* p_inode,struct file* p_file)
{
printk(KERN_EMERG "Hello_file_open \r\n");
return 0;
}
int Hello_driver_fops_release(struct inode* p_inode,struct file* p_file)
{
printk(KERN_EMERG "Hello_file_release \r\n");
}
long Hello_driver_fops_unlocked_ioctl(struct file* p_file ,unsigned int ID ,unsigned long cmd)
{
printk(KERN_EMERG "Hello_file_unlocked_ioctl \r\n");
printk(KERN_EMERG "argv1 is %d argv2 is %d \r\n" ,ID , cmd);
return 0;
}
module_init(Mini_Linux_Driver_Init);
module_exit(Mini_Linux_Driver_Exit);
其中的 设备名字(DEVICE_NAME )务必保持 与上文 注册的设备名字一致
而生成的设备节点名字(DEVICENODE_NAME)可以自己任意命名
先将驱动注册到总线上,这个驱动会执行probe函数
在probe函数中对设备注册为杂项设备
接下来编写设备节点的文件操作函数
改写Makefile文件 进行编译
obj-m += Mini_linux_device_module.o //这个修改为对应的编译文件
KDIR := /home/topeet/zImage/iTop4412_Kernel_3.0
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.order *.symvers
make 编译 生成 .ko文件
再make clean 删除中间文件
将生成的.ko文件传输到板子上
可以看见模块加载成功了,返回值为0 所以设备成功注册到总线上了
再查看一下设备总线文件下生成了Hello_device
再将驱动注册到总线上,id是-1,说明只有一个设备 ,status 是0 ,说明注册成功了
查看设备节点,发现生成了Hello设备节点
接下来编写应用程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc ,char* argv[])
{
int fd ;
int res;
char* file_node = argv[1];
char id = atoi(argv[2]);
char cmd = atoi(argv[3]);
fd=open(file_node,O_RDWR|O_NOCTTY|O_NDELAY);
if(fd==-1)
{
perror(file_node);
exit(EXIT_FAILURE);
}
res=ioctl(fd,id,cmd);
if(res==-1)
{
perror("ioctl");
close(fd);
exit(EXIT_FAILURE);
}
close(fd);
exit(EXIT_SUCCESS);
}
PS:ioctl这个函数传入的cmd和arg都是要做校检的,这里偷懒就没写了
编译
将其传输到板子上
确保你的驱动和设备都注册好了
调用我们刚刚写的程序
和我们的程序对比
好了,这就一整个杂项设备的驱动流程。