1 Star 0 Fork 0

linux-dev-org/imx6ull-driver-demo

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
sdriver_demo.c 6.44 KB
一键复制 编辑 原始数据 按行查看 历史
苏木 提交于 2025-01-07 22:52 +08:00 . 添加__ATTR()在属性文件中的应用demo
#include <linux/init.h> /* module_init module_exit */
#include <linux/kernel.h>
#include <linux/module.h> /* MODULE_LICENSE */
#include <linux/kobject.h>
#include <linux/slab.h>
#include "./timestamp_autogenerated.h"
#include "./version_autogenerated.h"
#include "./sdrv_common.h"
// #undef PRT
// #undef PRTE
#ifndef PRT
#define PRT printk
#endif
#ifndef PRTE
#define PRTE printk
#endif
typedef struct __SKOBJ_{
char skobj_name[32];
char name_attr[32];
int data;
struct kobject kobj;
}skobj_t;
skobj_t *skobject1 = NULL; // 定义kobject指针变量:skobject1
/**
* @brief skobj_attr_name_show()
* @note 读属性操作函数, cat 属性文件时调用这个函数,会把对应的值显示到终端
* @param [in]
* @param [out]
* @retval
*/
ssize_t skobj_attr_name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
ssize_t count = 0;
skobj_t *pskobj = container_of(kobj, skobj_t, kobj);
count = sprintf(buf, "%s\n", pskobj->name_attr);
return count;
}
/**
* @brief skobj_attr_name_store()
* @note 写属性操作文件, echo 属性文件时调用这个函数,用于echo x 中的 x 写入到属性对应的成员变量中
* @param [in]
* @param [out]
* @retval
*/
ssize_t skobj_attr_name_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
skobj_t *pskobj = container_of(kobj, skobj_t, kobj);
sscanf(buf, "%s\n", pskobj->name_attr);
return count;
}
/**
* @brief skobj_attr_data_show()
* @note 读属性操作函数, cat 属性文件时调用这个函数,会把对应的值显示到终端
* @param [in]
* @param [out]
* @retval
*/
ssize_t skobj_attr_data_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
ssize_t count = 0;
skobj_t *pskobj = container_of(kobj, skobj_t, kobj);
count = sprintf(buf, "%d\n", pskobj->data);
return count;
}
/**
* @brief skobj_attr_data_store()
* @note 写属性操作文件, echo 属性文件时调用这个函数,用于echo x 中的 x 写入到属性对应的成员变量中
* @param [in]
* @param [out]
* @retval
*/
ssize_t skobj_attr_data_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
skobj_t *pskobj = container_of(kobj, skobj_t, kobj);
sscanf(buf, "%d\n", &pskobj->data);
return count;
}
// 定义两个属性,用于管理 name_attr 和 data
// 注意,这里的mode赋值的时候不能用这些代表权限的宏,例如S_IRWXUGO,否则会在展开的时候出现问题
struct kobj_attribute s_attr_name = __ATTR(skobj_attr_name, 0664, skobj_attr_name_show, skobj_attr_name_store);
struct kobj_attribute s_attr_data = __ATTR(skobj_attr_data, 0664, skobj_attr_data_show, skobj_attr_data_store);
// 定义一个指针数组,将 attribute 对象全部放入数组中,方便后续赋值给 ktype 的 default_attrs 成员
struct attribute *s_attr[] = {
&s_attr_name.attr,
&s_attr_data.attr,
NULL,
};
/**
* @brief dynamic_kobj_release()
* @note 定义kobject的释放函数
* @param [in]
* @param [out]
* @retval
*/
static void dynamic_kobj_release(struct kobject *kobj)
{
skobj_t *pskobj = container_of(kobj, skobj_t, kobj);
PRT("kobject: (%p) \n", kobj);
kfree(pskobj);
}
/**
* @brief skobj_attr_show()
* @note 读属性操作函数, cat 属性文件时调用这个函数,会把对应的值显示到终端
* @param [in]
* @param [out]
* @retval
*/
ssize_t skobj_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
ssize_t count = 0;
struct kobj_attribute *pskobj_attr = container_of(attr, struct kobj_attribute, attr);
count = pskobj_attr->show(kobj, pskobj_attr, buf);
PRT("attr->name=%s count=%d\n", attr->name, count);
return count;
}
/**
* @brief skobj_attr_store()
* @note 写属性操作文件, echo 属性文件时调用这个函数,用于echo x 中的 x 写入到属性对应的成员变量中
* @param [in]
* @param [out]
* @retval
*/
ssize_t skobj_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)
{
struct kobj_attribute *pskobj_attr = container_of(attr, struct kobj_attribute, attr);
PRT("attr->name=%s count=%d\n", attr->name, count);
return pskobj_attr->store(kobj, pskobj_attr, buf, count);
}
// 自定义的 sysfs_ops 结构体,包含 show 和 store 函数指
struct sysfs_ops attr_sysfs_ops = {
.show = skobj_attr_show,
.store = skobj_attr_store,
};
// 自定义的 kobj_type 结构体,包含释放函数、默认属性和 sysfs_ops
struct kobj_type stype = {
.release = dynamic_kobj_release,
.sysfs_ops = &attr_sysfs_ops,
.default_attrs = s_attr,
};
/**
* @brief sdriver_demo_init()
* @note
* @param [in]
* @param [out]
* @retval
*/
static __init int sdriver_demo_init(void)
{
int ret = 0;
printk("*** [%s:%d]Build Time: %s %s, git version:%s ***\n", __FUNCTION__,
__LINE__, KERNEL_KO_DATE, KERNEL_KO_TIME, KERNEL_KO_VERSION);
PRT("sdriver_demo module init!\n");
// 创建kobject的第二种方法
// 1.使用kzalloc函数分配了一个kobject对象的内存
skobject1 = kzalloc(sizeof(skobj_t), GFP_KERNEL);
if(!skobject1)
{
ret = -1;
goto err_kzalloc;
}
snprintf(skobject1->skobj_name, sizeof(skobject1->skobj_name), "skobject1");
// 2.初始化并添加到内核中,名为"skobject1"。
ret = kobject_init_and_add(&skobject1->kobj, &stype, NULL, "%s", skobject1->skobj_name);
if(ret < 0)
{
PRTE("kobject_init_and_add fail!ret=%d\n", ret);
goto err_kobject_init_and_add;
}
return 0;
err_kobject_init_and_add:
kfree(skobject1);
err_kzalloc:
return ret;
}
/**
* @brief sdriver_demo_exit()
* @note
* @param [in]
* @param [out]
* @retval
*/
static __exit void sdriver_demo_exit(void)
{
// 释放之前创建的kobject对象
kobject_put(&skobject1->kobj);
PRT("sdriver_demo module exit!\n");
}
module_init(sdriver_demo_init); // 将__init定义的函数指定为驱动的入口函数
module_exit(sdriver_demo_exit); // 将__exit定义的函数指定为驱动的出口函数
/* 模块信息(通过 modinfo chrdev_led_demo 查看) */
MODULE_LICENSE("GPL v2"); /* 源码的许可证协议 */
MODULE_AUTHOR("sumu"); /* 字符串常量内容为模块作者说明 */
MODULE_DESCRIPTION("Description"); /* 字符串常量内容为模块功能说明 */
MODULE_ALIAS("module's other name"); /* 字符串常量内容为模块别名 */
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/linux-dev-org/imx6ull-driver-demo.git
git@gitee.com:linux-dev-org/imx6ull-driver-demo.git
linux-dev-org
imx6ull-driver-demo
imx6ull-driver-demo
main

搜索帮助