21,618
社区成员




beep.c文件:
#include "chdev_build.h"
extern dev_nod_error error_dev;
typedef struct {
dev_id device_id;
struct cdev cdev_beep;
dev_node device_node;
struct devcie_node * nd;
int gpio_id;
} beep_device;
beep_device beep_structure;
static int beep_file_open(struct node * node_in, struct file * file_in){
file_in -> private_data = &beep_structure;
return 0;
}
static ssize_t beep_file_write(struct file * file_in, const char * buffer_t, size_t size, loff_t * loff_t_in){
char kernel_buf[32] = {0}; // 内核缓冲区
int value;
int ret;
beep_device * temp = (beep_device *)file_in->private_data;
// 1. 检查写入长度是否有效
if (buffer_size > sizeof(kernel_buf) - 1)
return -EINVAL;
// 2. 从用户空间复制数据到内核空间
if (copy_from_user(kernel_buf, buffer_t, buffer_size))
return -EFAULT;
// 3. 解析控制指令(示例:字符串转数字)
ret = kstrtoint(kernel_buf, 10, &value);
if (ret < 0) {
pr_err("Invalid value: %s\n", kernel_buf);
return -EINVAL;
}
// 4. 根据值控制硬件
if (value == 1) {
gpio_set_value(temp ->gpio_id, 1); // 点亮LED
} else if (value == 0) {
gpio_set_value(temp ->gpio_id, 0); // 熄灭LED
} else {
return -EINVAL;
}
// 5. 返回实际写入字节数
return buffer_size;
}
static ssize_t beep_file_release(struct inode * inode_in, struct file * file_in){
file_in -> private_data = NULL;
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.open = beep_file_open,
.write = beep_file_write,
.release = beep_file_release,
};
static int __init beep_init(void){
int ret = 0;
printk(KERN_ERR "print in beep init\r\n");
ret = register_chrdev_reg(&beep_structure.device_id);
if (ret < 0){
goto register_chrdev_error;
}
ret = chrdev_operation_build(&beep_structure.cdev_beep, &fops, &beep_structure.device_id);
if (ret < 0){
goto char_dev_operation_build_error;
}
ret = chrdev_device_node_build(&beep_structure.device_node, &beep_structure.device_id);
if (ret < 0){
goto chardev_device_node_build_error;
}
beep_structure.nd = of_find_node_by_path("/beep_pin");
if (beep_structure.nd == NULL){
printk(KERN_ERR "error in find nod by path\r\n");
ret = -1;
goto find_node_by_path_error;
}
beep_structure.gpio_id = of_get_named_gpio(beep_structure.device_node, "beep-gpios", 1);
if (beep_structure.gpio_id <0){
printk(KERN_ERR "error in get named gpio\r\n");
ret = -ENAVAIL;
goto get_named_gpio_error;
}
printk("led gpio = %d\r\n", beep_structure.gpio_id);
ret = gpio_request(beep_structure.gpio_id, DEV_NAME);
if (ret){
printk(KERN_ERR "error in gpio request\r\n");
ret = -ENAVAIL;
goto gpio_error:
}
ret = gpio_direction_output(beep_structure.gpio_id, 1){
if (ret){
printk(KERN_ERR "error in gpio direction set\r\n");
ret = -ENAVAIL;
goto gpio_dir_fail;
}
}
gpio_set_value(beep_structure.gpio_id, 0);
return 0;
gpio_dir_fail:
gpio_free(beep_structure.cdev_beep);
printk("cdev gpio fail\r\n");
gpio_error:
;
find_node_by_path_error:
device_destroy(beep_structure.device_node.dev_device);
printk("device destory\r\n");
chardev_device_node_build_error:
switch (error_dev){
case device_error:
class_destroy(beep_structure.device_node.dev_class);
printk("class destory\r\n");
case class_error:
cdev_del(&beep_structure.cdev_beep);
printk("char devcie delite\r\n");
};
char_dev_operation_build_error:
unregister_chrdev_region(beep_structure.device_id.devid, DEV_COUNT);
printk("unregister char device \r\n");
register_chrdev_error:
;
return ret;
}
static void __exit beep_exit(void){
gpio_free(beep_structure.cdev_beep);
printk("cdev gpio fail\r\n");
device_destroy(beep_structure.device_node.dev_device);
printk("device destory\r\n");
class_destroy(beep_structure.device_node.dev_class);
printk("class destory\r\n");
cdev_del(&beep_structure.cdev_beep);
printk("char devcie delite\r\n");
unregister_chrdev_region(beep_structure.device_id.devid, DEV_COUNT);
printk("unregister char device \r\n");
}
/* access for module entery and exit */
module_init(beep_init);
module_exit(beep_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chentan tech");
config.h 文件:
#ifndef __CONFIG_H
#define __CONFIG_H
#define DEV_NAME "beep"
#define DEV_COUNT 1
#endif
chdev_build.h文件:
#ifndef __BEEP_H
#define __BEEP_H
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/sysfs.h>
#include <linux/gpio.h>
#include "config.h"
#if !defined(DEV_NAME)
#error "DEV_NAME should be defind"
#endif
#if !defined(DEV_COUNT)
#error "DEV_COUNT should be defind"
#endif
typedef struct {
dev_t devid;
int major;
int minor;
} dev_id;
typedef struct {
struct class * dev_class;
struct device * dev_device;
} dev_node;
typedef enum {
class_error,
device_error
} dev_nod_error;
dev_nod_error error_dev;
int register_chrdev_reg(dev_id * dev_id_in);
int chrdev_operation_build(struct cdev * cdev_in, struct file_operations * fops, dev_id * dev_id_in);
int chrdev_device_node_build(dev_node * dev_node_in, dev_id * dev_id_in);
#endif
chdev_build.c文件:
#include "chdev_build.h"
int register_chrdev_reg(dev_id * dev_id_in){
int ret = 0;
if (dev_id_in ->major){
dev_id_in ->devid = MKDEV(dev_id_in -> major, dev_id_in -> minor);
ret = register_chrdev_region(dev_id_in ->devid, DEV_COUNT, DEV_NAME);
}
else {
ret = alloc_chrdev_region(&dev_id_in ->devid, 0, DEV_COUNT, DEV_NAME);
dev_id_in ->major = MAJOR(dev_id_in ->devid);
dev_id_in ->minor = MINOR(dev_id_in ->minor);
}
if (ret < 0){
printk(KERN_ERR "error in reg chrdev\r\n");
}
return ret;
}
int chrdev_operation_build(struct cdev * cdev_in, struct file_operations * fops, dev_id * dev_id_in){
int ret = 0;
cdev_init(cdev_in, fops);
ret = cdev_add(cdev_in, dev_id_in -> devid , DEV_COUNT);
if (ret < 0){
printk(KERN_ERR "error in cdev add\r\n");
}
return ret;
}
int chrdev_device_node_build(dev_node * dev_node_in, dev_id * dev_id_in){
int ret = 0;
dev_node_in ->dev_class = class_create(THIS_MODULE, DEV_NAME);
if (IS_ERR(dev_node_in ->dev_class)){
printk(KERN_ERR "dev_class create error\r\n");
ret = PTR_ERR(dev_node_in ->dev_class);
error_dev = class_error;
return ret;
}
dev_node_in ->dev_device = device_create(dev_node_in ->dev_class, NULL, dev_id_in ->devid, NULL, DEV_NAME);
if (IS_ERR(dev_node_in ->dev_device)){
printk(KERN_ERR "dev_device create error\r\n");
ret = PTR_ERR(dev_node_in ->dev_device);
error_dev = device_error;
return ret;
}
return 1;
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chentan tech");这是我的源代码,分成了四个文件,但是用insmod加载之后什么反应都没有,并且一点输出都没有,检查了/dev下也没有一个创建好的节点。