- 我们的目的写出一个容易扩展到各种芯片、各种板子的按键驱动程序,所以驱动程序分为上下两层:
 
① button_drv.c 分配/设置/注册 file_operations 结构体
起承上启下的作用,向上提供 button_open,button_read 供 APP 调用。
而这 2 个函数又会调用底层硬件提供的 p_button_opr 中的 init、read 函数操作硬件。
② board_xxx.c 分配/设置/注册 button_operations 结构体
这个结构体是我们自己抽象出来的,里面定义单板 xxx 的按键操作函数。

- 抽象出button_opeartions结构体 ```c struct button_operations { int count; void (init) (int which); int (read) (int which); };
 
void register_button_operations(struct button_operations *opr); void unregister_button_operations(void);
- 实现button_opeartions结构体,并注册到上层的按键驱动程序中```cstatic void board_xxx_button_init_gpio (int which){printk("%s %s %d, init gpio for button %d\n", __FILE__, __FUNCTION__, __LINE__, which);}static int board_xxx_button_read_gpio (int which){printk("%s %s %d, read gpio for button %d\n", __FILE__, __FUNCTION__, __LINE__, which);return 1;}static struct button_operations my_buttons_ops ={.count = 2,.init = board_xxx_button_init_gpio,.read = board_xxx_button_read_gpio,};int board_xxx_button_init(void){register_button_operations(&my_buttons_ops);return 0;}void board_xxx_button_exit(void){unregister_button_operations();}module_init(board_xxx_button_init);module_exit(board_xxx_button_exit);MODULE_LICENSE("GPL");
- 实现上层的按键驱动 ```c static int major = 0;
 
static struct button_operations p_button_opr; static struct class button_class;
static int button_open (struct inode inode, struct file file) { int minor = iminor(inode); p_button_opr->init(minor); return 0; }
static ssize_t button_read (struct file file, char __user buf, size_t size, loff_t *off) { unsigned int minor = iminor(file_inode(file)); char level; int err;
level = p_button_opr->read(minor);err = copy_to_user(buf, &level, 1);return 1;
}
static struct file_operations button_fops = { .open = button_open, .read = button_read, };
void register_button_operations(struct button_operations *opr) { int i;
p_button_opr = opr;for (i = 0; i < opr->count; i++){/* 在底层代码注册button_operations时创建device */device_create(button_class, NULL, MKDEV(major, i), NULL, "100ask_button%d", i);}
}
void unregister_button_operations(void) { int i;
for (i = 0; i < p_button_opr->count; i++){device_destroy(button_class, MKDEV(major, i));}
}
EXPORT_SYMBOL(register_button_operations); EXPORT_SYMBOL(unregister_button_operations);
int button_init(void) { major = register_chrdev(0, “100ask_button”, &button_fops);
button_class = class_create(THIS_MODULE, "100ask_button");if (IS_ERR(button_class))return -1;return 0;
}
void button_exit(void) { class_destroy(button_class); unregister_chrdev(major, “100ask_button”); }
module_init(button_init); module_exit(button_exit); MODULE_LICENSE(“GPL”); ```
- 将上层的按键驱动和底层board的驱动程序都编译成.ko模块(底层board依赖于上层)
 - 底层代码调用 register_button_operations 函数,向上提供button_operations这个结构体指针
 
