本文完成继上篇 iTOP-4412 虚拟平台注册杂项字符设备,后对应的字符设备驱动注册。
一、驱动头文件
1、platform_device.h
路径:iTop4412_Kernel_3.0/include/linux/platform_device.h
部分内容如下:
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(struct platform_driver *);
驱动注册platform_driver_register
驱动卸载函数platform_driver_unregister
结构体platform_driver 指针函数功能如下:
probe函数 :platform_match函数匹配之后,驱动调用的初始化函数
remove函数 :移除驱动函数
shutdown函数 :掉电驱动函数
suspend函数 :悬挂(休眠)驱动函数
resume函数 :休眠后恢复驱动
device_driver:数据结构的两个参数
– name和注册的设备name要一致
– owner一般赋值THIS_MODULE
id_table结构体: 可以使驱动支持更多的设备,通过这个文件具体了解。
https://blog.csdn.net/mcgrady_tracy/article/details/38980991
2、miscdevice.h
路径:iTop4412_Kernel_3.0/include/linux/miscdevice.h
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
extern int misc_register(struct miscdevice * misc);
extern int misc_deregister(struct miscdevice *misc);
常用的参数
– .minor 设备号
– .name 生成设备节点的名称
– .fops 指向一个设备节点文件
misc_register :注册杂项设备
misc_deregister :注销杂项设备
这两个函数在iTop4412_Kernel_3.0/drivers/char/misc.c中定义
3、fs.h
路径:iTop4412_Kernel_3.0/include/linux/fs.h
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
......
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
int (*open) (struct inode *, struct file *);
......
};
文件的结构体file_operations参数很多,根据需求选择必选的是参数是
– .owner 一般是THIS_MODULE,
– .open 打开文件函数
- .read 读函数
- .write 写函数
– .release 关闭文件函数
– .unlocked_ioctl 对GPIO的操作,应用向底层驱动传值
二、注册杂项设备
杂项设备是对一部分字符设备的封装,杂项设备主设备号 是10,就主设备号只有255个,所以我们在主设备号10下注册次设备。
[root@iTOP-4412]# cat /proc/devices
Character devices:
1 mem
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
10 misc
13 input
21 sg
29 fb
81 video4linux
89 i2c
108 ppp
三、在目录iTop4412_Kernel_3.0/drivers/char/添加文件itop4412_hello.c
#include <linux/init.h>
#include <linux/module.h>
/*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
#include <linux/platform_device.h>
/*注册杂项设备头文件*/
#include <linux/miscdevice.h>
/*注册设备节点的文件结构体*/
#include <linux/fs.h>
#define DRIVER_NAME "hello_device"
#define DEVICE_NAME "hello" //设备结点名字 上层运用软件调用驱动结点
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("TOPEET");
static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
printk("cmd is %d,arg is %ld\n",cmd,arg);
return 0;
}
static int hello_release(struct inode *inode, struct file *file){
printk(KERN_EMERG "hello release\n");
return 0;
}
static int hello_open(struct inode *inode, struct file *file){
printk(KERN_EMERG "hello open\n");
return 0;
}
static struct file_operations hello_ops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.unlocked_ioctl = hello_ioctl,
};
static struct miscdevice hello_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &hello_ops,
};
static int hello_probe(struct platform_device *pdv){
printk(KERN_EMERG "\tinitialized\n");
misc_register(&hello_dev);
return 0;
}
static int hello_remove(struct platform_device *pdv){
printk(KERN_EMERG "\tremove\n");
misc_deregister(&hello_dev);
return 0;
}
static void hello_shutdown(struct platform_device *pdv){
;
}
static int hello_suspend(struct platform_device *pdv,pm_message_t pmt){
return 0;
}
static int hello_resume(struct platform_device *pdv){
return 0;
}
struct platform_driver hello_driver = {
.probe = hello_probe,
.remove = hello_remove,
.shutdown = hello_shutdown,
.suspend = hello_suspend,
.resume = hello_resume,
.driver = {
.name = DRIVER_NAME, //这个要跟注册的设备名字要相同
.owner = THIS_MODULE,
}
};
static int hello_init(void)
{
int DriverState;
printk(KERN_EMERG "HELLO WORLD enter!\n");
DriverState = platform_driver_register(&hello_driver);
printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "HELLO WORLD exit!\n");
platform_driver_unregister(&hello_driver);
}
module_init(hello_init);
module_exit(hello_exit);
四、在iTop4412_Kernel_3.0/drivers/char/Makefile添加内容
obj-$(CONFIG_HELLO_CTL) += itop4412_hello.o
五、编译
make zImage
六、查看是否生成设备结点
[root@iTOP-4412]# ls
AGPS ion ppp tty3
HPD keychord ptmx tty4
adc kmem pts ttyGS0
alarm kmsg ram0 ttyGS1
android_adb leds ram1 ttyGS2
ashmem log ram10 ttyGS3
buzzer_ctl loop0 ram11 ttyS0
console loop1 ram12 ttyS1
cpu_dma_latency loop2 ram13 ttyS2
exynos-mem loop3 ram14 ttyS3
fb0 loop4 ram15 ttySAC0
fb1 loop5 ram2 ttySAC1
fb10 loop6 ram3 ttySAC2
fb11 loop7 ram4 ttySAC3
fb2 mali ram5 uinput
fb3 mapper ram6 ump
fb4 max485_ctl_pin ram7 urandom
fb5 mem ram8 usb_accessory
fb6 mmcblk0 ram9 usbdev1.1
fb7 mmcblk0p1 random usbdev1.2
fb8 mmcblk0p2 rc522 usbdev1.3
fb9 mmcblk0p3 relay_ctl video0
fimg2d mmcblk0p4 root video1
full mmcblk1 rtc0 video11
fuse mmcblk1p1 rtc1 video12
gps mmcblk1p2 s3c-mem video16
hello mmcblk1p3 s3c-mfc video2
i2c-0 mmcblk1p4 shm video20
i2c-1 mtp_usb snd video3
i2c-3 network_latency srp watchdog
i2c-4 network_throughput srp_ctrl xt_qtaguid
i2c-5 null tty zero
i2c-7 pmem tty1
input pmem_gpu1 tty2
我看到已经有hello了。