erDiagram
module_init ||--o{ gpio_drv_init : init
gpio_drv_init ||--|{ setup_timer : init_timer
setup_timer ||--|{ key_timer_expire : irq_function
key_timer_expire ||--|{ gpio_get_value : gpio_get_value
gpio_get_value ||--|{ put_key : put_key
gpio_drv_init ||--|{ add_timer : start_timer
add_timer ||--|{ key_timer_expires : update_timer_expires
gpio_drv_init ||--|{ request_irq : register_irq
request_irq ||--|{ gpio_key_isr : irq_function
gpio_key_isr ||--|{ mod_timer : update_timer_expires
gpio_drv_init ||--|{ register_chrdev : register_chrdev
register_chrdev ||--|{ gpio_operations_drv : file_operations
gpio_operations_drv ||--|{ read : gpio_drv_read
read ||--|{ is_key_buf_empty_true : return_-EINVAL
read ||--|{ get_key : get_key
get_key ||--|{ copy_to_user : copy_to_user
gpio_drv_init ||--|{ class_create : class_create
gpio_drv_init ||--|{ device_create : device_create
module_exit ||--o{ gpio_drv_exit : exit
gpio_drv_exit ||--o{ device_destroy : device_destroy
gpio_drv_exit ||--o{ class_destroy : class_destroy
gpio_drv_exit ||--o{ unregister_chrdev : unregister_chrdev
gpio_drv_exit ||--o{ free_irq : free_irq
gpio_drv_exit ||--o{ del_timer : del_timer
应用程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd;
int len;
int key;
if (argc < 1) {
printf("Usage: %s </dev/xxx>\n", argv[0]);
return -1;
}
fd = open(argv[0], O_RDWR);
if (fd < 0)
{
printf("open %s err\n", argv[1]);
return -1;
}
while (1) {
len = read(fd, &key, sizeof(key));
if (len == sizeof(key)) {
printf("key: %d", key);
} else {
printf("read err %d\n", len);
}
}
return 0;
}
驱动程序
static int major = 0
static struct class *gpio_class
struct gpio_desc {
int gpio
int irq
char *name
int key
struct timer_list key_timer
}
static struct gpio_desc gpios[2] = {
{131, 0, "gpio_100ask_1", 1, },
{132, 0, "gpio_100ask_2", 2, },
}
/** 环形缓冲区 */
static int g_keys[BUF_LEN]
static int r, w
static int is_key_buf_empty(void) {
return (r ==w)
}
static int is_key_buf_full(void) {
return (r == NEXT_POS(w))
}
static void put_key(int key) {
if (!is_key_buf_full()) {
g_keys[w] = key
w = NEXT_POS(w)
}
}
static int get_key(void) {
int key = 0
if (!is_key_buf_empty()) {
key = g_keys[r]
r = NEXT_POS(r)
}
return key
}
static void key_timer_expire(unsigned long data) {
struct gpio_desc *gpio_desc = (struct gpio_desc *)data
int val = gpio_get_value(gpio_desc->gpio)
/** 引脚key = 1, 引脚值 = 1, key = 1000 0001 */
int key = (gpio_desc->key) | (val << 8)
put_key(key)
}
static irqreturn_t gpio_key_isr(int irq, void *dev_id) {
struct gpio_desc *gpio_desc = dev_id
mod_timer(&gpio_desc->key_timer, jiffies + HZ/5)
return IRQ_HANDLED
}
static ssize_t gpio_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset) {
int err
int key
if (is_key_buf_empty() && (file->f_flags & O_NONBLOCK)) {
return -EINVAL
}
key = get_key()
err = copy_to_user(buf, &key, sizeof(key))
return sizeof(key)
}
/** 应用函数没有用到 */
// static ssize_t gpio_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset){
// unsigned char ker_buf[2]
// int err
// /** gpio引脚就注册两个 */
// if (size != 2) {
// return -EINVAL
// }
// err = copy_from_user(ker_buf, buf, size)
// if (ker_buf[0] >= sizeof(gpios)/sizeof(gpios[0])) {
// return -EINVAL
// }
// gpio_set_value(gpios[ker_buf[0]].gpio, ker_buf[1])
// return size
// }
const struct file_operations gpio_operations_drv = {
.owner = THIS_MODULE,
.read = gpio_drv_read,
// .write = gpio_drv_write, /** 应用函数没有用到 */
}
static int __init gpio_drv_init(void) {
int i
int count = sizeof(gpios) / sizeof(gpios[0])
for (i = 0
setup_timer(&gpios[i].key_timer, key_timer_expire, (unsigned long)&gpios[i])
gpios[i].key_timer.expires = ~0
add_timer(&gpios[i].key_timer)
gpios[i].irq = gpio_to_irq(gpios[i].gpio)
request_irq(gpios[i].irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "template_gpio_irq", &gpios[i])
}
major = register_chrdev(0, "template_gpio_dev", &gpio_operations_drv)
gpio_class = class_create(THIS_MODULE, "template_gpio_class")
if (IS_ERR(gpio_class)) {
unregister_chrdev(major, "template_gpio_dev")
return PTR_ERR(gpio_class)
}
device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "template_gpio_device")
return 0
}
static void __exit gpio_drv_exit(void) {
int i
int count = sizeof(gpios) / sizeof(gpios[0])
device_destroy(gpio_class, MKDEV(major, 0))
class_destroy(gpio_class)
unregister_chrdev(major, "template_gpio_dev")
for (i = 0
free_irq(gpios[i].irq, &gpios[i])
del_timer(&gpios[i].key_timer)
}
}
module_init(gpio_drv_init)
module_exit(gpio_drv_exit)