雜項設(shè)備可以說是對一部分字符設(shè)備的封裝屁商,還有一部分不好歸類驅(qū)動也歸到雜項設(shè)備。
?1為什么會引入雜項設(shè)備?
? ? ? ? ?第一蜡镶、節(jié)省主設(shè)備號
? ? ? ? ? ? ? ?–如果所有的驅(qū)動都是用字符設(shè)備雾袱,那么所有的設(shè)備號很快就用完了,總共就255個主設(shè)備號官还。
? ? ? ? ?第二芹橡、驅(qū)動寫起來相對簡單
? ? ? ? ? ? ?–如果直接使用封裝好的雜項設(shè)備,那么就可以減少一步注冊主設(shè)備號的過程
?2雜項設(shè)備初始化文件
? ? ? ? 雜項設(shè)備初始化部分源文件“drivers/char/ misc.c”望伦,這一部分通過Makefile可知林说,是強(qiáng)制編譯的。
?3 注冊文件
? ? ? ? include/linux/miscdevice.h 頭文件
? ? ? ? struct miscdevice? {
? ? ? ? ? ? ? ? int minor;?常用的參數(shù),設(shè)備號
? ? ? ? ? ? ? ? const char *name;?常用的參數(shù),生成設(shè)備節(jié)點(diǎn)的名稱
? ? ? ? ? ? ? ? const struct file_operations *fops; ?常用的參數(shù), 指向一個設(shè)備節(jié)點(diǎn)文件
? ? ? ? ? ? ? ? struct list_head list;
? ? ? ? ? ? ? ? struct device *parent;
? ? ? ? ? ? ? ? struct device *this_device;
? ? ? ? ? ? ? ? const char *nodename;
? ? ? ? ? ? ? ?mode_t mode;
? ? ? ?};
? ? ? ? /*
? ? ? ? * NOTE:
? ? ? ?* all file operations except setlease can be called without
? ? ? ?* the big kernel lock held in all filesystems.
? ? ? */
? ? ? ? /*頭文件 include/linux/fs.h*/
? ? ? struct file_operations {
? ? ? ? ? ? ? ? struct module *owner;?必選的是參數(shù),一般是THIS_MODULE
? ? ? ? ? ? ? ? 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 *);
? ? ? ? ? ? ? ? ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
? ? ? ? ? ? ? ? ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
? ? ? ? ? ? ? ?int (*readdir) (struct file *, void *, filldir_t);
? ? ? ? ? ? ? ?unsigned int (*poll) (struct file *, struct poll_table_struct *);
? ? ? ? ? ? ? ? /* remove by cym 20130408 support for MT660.ko */
? ? ? ? ? ? ? ? #if 0
? ? ? ? ? ? ? ? ? ? ? ?//#ifdef CONFIG_SMM6260_MODEM
? ? ? ? ? ? ? ? ? ? ? ?#if 1// liang, Pixtree also need to use ioctl interface...
? ? ? ? ? ? ? ? ? ? ? ? ? int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
? ? ? ? ? ? ? ? ? ? ?#endif
? ? ? ? ? ? ? ? ?#endif
? ? ? ? ? ? ? ? ?/* end remove */
? ? ? ? ? ? ? ? ? ? ? ? long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);對GPIO的操作屯伞,應(yīng)用向底層驅(qū)動傳值
? ? ? ? ? ? ? ? ? ? ? ? long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
? ? ? ? ? ? ? ? ? ? ? ? int (*mmap) (struct file *, struct vm_area_struct *);
? ? ? ? ? ? ? ? ? ? ? ? int (*open) (struct inode *, struct file *);?必選的是參數(shù)
? ? ? ? ? ? ? ? ? ? ? ? int (*flush) (struct file *, fl_owner_t id);
? ? ? ? ? ? ? ? ? ? ? ? int (*release) (struct inode *, struct file *);?必選的是參數(shù)
? ? ? ? ? ? ? ? ? ? ? ? int (*fsync) (struct file *, int datasync);
? ? ? ? ? ? ? ? ? ? ? ? ?int (*aio_fsync) (struct kiocb *, int datasync);
? ? ? ? ? ? ? ? ? ? ? ? ?int (*fasync) (int, struct file *, int);
? ? ? ? ? ? ? ? ? ? ? ? ?int (*lock) (struct file *, int, struct file_lock *);
? ? ? ? ? ? ? ? ? ? ? ? ?ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
? ? ? ? ? ? ? ? ? ? ? ? ?int (*check_flags)(int);
? ? ? ? ? ? ? ? ? ? ? ? ?int (*flock) (struct file *, int, struct file_lock *);
? ? ? ? ? ? ? ? ? ? ? ? ?ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
? ? ? ? ? ? ? ? ? ? ? ? ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
? ? ? ? ? ? ? ? ? ? ? ??int (*setlease)(struct file *, long, struct file_lock **);
? ? ? ? ? ? ? ? ? ? ? ?long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len);
? ? ? ? ? ? ? ? ? ? ? /* add by cym 20130408 support for MT6260 and Pixtree */
? ? ? ? ? ? ? ? ? ? ?#if defined(CONFIG_SMM6260_MODEM) || defined(CONFIG_USE_GPIO_AS_I2C)
? ? ? ? ? ? ? ? ? ? ? ? ? ? int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
? ? ? ? ? ? ? ? ? ? #endif
? ? ? ? ? ? ? ? ? /* end add */
? ? ? ? };
4.例子(devicenode_linux_module.c)
? ? ? ? #include
? ? ? ? #include
? ? ? ? /*驅(qū)動注冊的頭文件腿箩,包含驅(qū)動的結(jié)構(gòu)體和注冊和卸載的函數(shù)*
? ? ? ? /#include
? ? ? ? /*注冊雜項設(shè)備頭文件*/
? ? ? ? #include
? ? ? ? /*注冊設(shè)備節(jié)點(diǎn)的文件結(jié)構(gòu)體*/
? ? ? ? #include
? ? ? ? #define DRIVER_NAME "hello_ctl"
? ? ? ? #define DEVICE_NAME "hello_ctl123"
? ? ? ? MODULE_LICENSE("Dual BSD/GPL");
? ? ? ? MODULE_AUTHOR("TOPEET");
? ? ? ? /*ioctl*/? ? ? ?
? ? ? ? static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){
? ? ? ? ? ? ? ? printk("cmd is %d,arg is %d\n",cmd,arg);
? ? ? ? ? ? ? ? return 0;
? ? ? ? }
? ? ? ? ? /*close*/
? ? ? ? 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 "\tprobe initialized\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)
? ? ? ? {
? ? ? ? ? ? ? ?printk(KERN_EMERG "HELLO WORLD enter!\n");
? ? ? ? ? ? ? ?int 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);
5.Makefile
? ? ? ? #!/bin/bash
? ? ? ?#通知編譯器我們要編譯模塊的哪些源碼
? ? ? ? #這里是編譯devicenode_linux_module.c這個文件編譯成中間文件devicenode_linux_module.o
? ? ? ??obj-m += devicenode_linux_module.o
? ? ? ? #源碼目錄變量,這里用戶需要根據(jù)實(shí)際情況選擇路徑
? ? ? ? #作者是將Linux的源碼拷貝到目錄/home/topeet/android4.0下并解壓的
? ? ? ??KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0
? ? ? ? #當(dāng)前目錄變量
? ? ? ?PWD ?= $(shell pwd)
? ? ? ?#make命名默認(rèn)尋找第一個目標(biāo)
? ? ? ?#make -C就是指調(diào)用執(zhí)行的路徑
? ? ? ? #$(KDIR)Linux源碼目錄劣摇,作者這里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0
? ? ? ? #$(PWD)當(dāng)前目錄變量
? ? ? ? #modules要執(zhí)行的操作
all:
make -C $(KDIR) M=$(PWD) modules
#make clean執(zhí)行的操作是刪除后綴為o的文件
clean:
rm -rf *.o
6.make,編譯后同驅(qū)動注冊一樣