一. 驱动层
1.1 关于sys文件系统
a.对于DEVICE_ATTR,其定义是#define DEVICE_ATTR(_name, _mode, _show, _store)
填充DEVICE_ATTR: 名称、权限位、读函数、写函数
static DEVICE_ATTR( power_on , S_IRUGO | S_IWUSR,NULL, hello_set_power);
DEVICE_ATTR中名称是power_on,即在/sys目录下创建了一个叫power_on的文件
b. 创建接口
当DEVICE_ATTR中名称是power_on,则构体struct attribute *dev_attrs[]中
其中的名字必须是&dev_attr_ power_on .attr,如下蓝色所示
static struct attribute * hello_attributes [] = {
&dev_attr_ power_on .attr,
NULL
};
c. 然后再封装到atrribute_group中去
static const struct attribute_group hello_attr_group = {
.attrs = hello_attributes ,
};
d. 最后调用sysfs_create_group(&pdev->dev.kobj, &hello_attr_group);创建接口
f. 上层应用调用sys接口时,只需在/sys/device/platform/hello/目录中, echo 1 > ./power_on就完成了一次 write操作,对应到 kernel,调用了驱动中的 "store"。同理,cat ./power_on时就调用调用 "show"
1.2 驱动代码
1.3 代码打包
sys.rar
(下载后改名为sys.rar)
二. 应用层
2.1 说明
测试时可以直接调用echo 1 > /sys/devices/platform/hello/power_on
代码中open --> /sys/devices/platform/hello/power_on
write 即可
2.2 代码
2.3 代码打包
app.rar
(下载后改名为app.tar.gz)
1.1 关于sys文件系统
a.对于DEVICE_ATTR,其定义是#define DEVICE_ATTR(_name, _mode, _show, _store)
填充DEVICE_ATTR: 名称、权限位、读函数、写函数
static DEVICE_ATTR( power_on , S_IRUGO | S_IWUSR,NULL, hello_set_power);
DEVICE_ATTR中名称是power_on,即在/sys目录下创建了一个叫power_on的文件
b. 创建接口
当DEVICE_ATTR中名称是power_on,则构体struct attribute *dev_attrs[]中
其中的名字必须是&dev_attr_ power_on .attr,如下蓝色所示
static struct attribute * hello_attributes [] = {
&dev_attr_ power_on .attr,
NULL
};
c. 然后再封装到atrribute_group中去
static const struct attribute_group hello_attr_group = {
.attrs = hello_attributes ,
};
d. 最后调用sysfs_create_group(&pdev->dev.kobj, &hello_attr_group);创建接口
f. 上层应用调用sys接口时,只需在/sys/device/platform/hello/目录中, echo 1 > ./power_on就完成了一次 write操作,对应到 kernel,调用了驱动中的 "store"。同理,cat ./power_on时就调用调用 "show"
1.2 驱动代码
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/device.h>
- #include <linux/ioport.h>
- #include <linux/errno.h>
- #include <linux/workqueue.h>
- #include <linux/platform_device.h>
- #include <linux/types.h>
- #include <linux/io.h>
-
- typedef struct {
- int num;
- }hello_priv;
- //当上导调用 echo 111 > ./power_on时, buf的内容就是这个字符串“111”,即参数
- static ssize_t hello_set_power(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
- {
- hello_priv* prv = dev_get_drvdata(dev);
- if ('0' == buf[0]) //shutdown
- {
- printk(KERN_NOTICE "cong: %s:%s[%d]: buf=%s, prv->num=%d", __FILE__,__FUNCTION__, __LINE__,buf, prv->num);
- }else if ('1' == buf[0]) //poweron
- {
- printk(KERN_NOTICE "cong: %s:%s[%d]: buf=%s, prv->num=%d", __FILE__,__FUNCTION__, __LINE__,buf, prv->num);
- }
- return count;
- }
- //1. 设置DEVICE_ATTR: 名称power_on必须与attribute中的名称对应,
- static DEVICE_ATTR(power_on, S_IRUGO | S_IWUSR,NULL, hello_set_power); //show接口为空,只有store接口,即只支持写不技持读
- //2. 设置DEVICE_ATTR
- static struct attribute *hello_attributes[] = {
- &dev_attr_power_on.attr, //dev_attr_****.attr中间的××××必须与DEVICE_ATTR中的名称对应
- NULL
- };
- //3. 封装到attribute_group中去
- static const struct attribute_group hello_attr_group = {
- .attrs = hello_attributes,
- };
-
- static int __init hello_probe(struct platform_device *pdev)
- {
- int rc;
- hello_priv* prv;
-
- prv = devm_kzalloc(&pdev->dev, sizeof(hello_priv), GFP_KERNEL);
- if (!prv) {
- dev_err(&pdev->dev, "failed to allocate hello\n");
- return -ENOMEM;
- }
-
- prv->num = 2;
-
- platform_set_drvdata(pdev,prv);
-
- rc = sysfs_create_group(&pdev->dev.kobj, &hello_attr_group); //4.调用sysfs_create_group创建/sys下的文件
- if (rc) {
- dev_err(&pdev->dev,"failed to create hello sysfs group\n");
- goto fail;
- }
-
- return 0;
- fail:
- return rc;
- }
-
- struct platform_driver hello_driver = {
- .driver = {
- .name = "hello",
- .owner = THIS_MODULE,
- },
- .probe = hello_probe,
- };
-
- static struct platform_device hello_device =
- {
- .name = "hello",
- .id = -1,
- };
-
- static int __init hello_init(void)
- {
- int ret;
-
- ret = platform_device_register(&hello_device);
- if (ret != 0)
- printk(KERN_NOTICE "cong: %s:%s[%d]: error", __FILE__,__FUNCTION__, __LINE__);
-
- ret = platform_driver_register(&hello_driver);
- return ret;
- }
-
- static void __init hello_exit(void)
- {
- platform_driver_unregister(&hello_driver);
- }
-
- module_init(hello_init);
- module_exit(hello_exit);
-
- MODULE_DESCRIPTION("GPIO Controller Driver");
- MODULE_AUTHOR("cong");
- MODULE_LICENSE("GPL");
![](https://i-blog.csdnimg.cn/blog_migrate/f5eb4426879d9c4b4b2deb15679e0746.png)
二. 应用层
2.1 说明
测试时可以直接调用echo 1 > /sys/devices/platform/hello/power_on
代码中open --> /sys/devices/platform/hello/power_on
write 即可
2.2 代码
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <linux/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
- #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)
-
- #define POWER_ON "power_on"
-
- int usage()
- {
- printf("usage:\n");
- printf("./test power_on <0/1> : 0-->poweron; 1-->poweroff \n");
- return 0;
- }
-
- int power_on(char* arg)
- {
- int fd;
- if( ('0'!=arg[0]) && ('1'!=arg[0]))
- {
- dbmsg("bad args");
- return -1;
- }
- fd = open("/sys/devices/platform/hello/power_on", O_RDWR);
- if(fd < 0)
- {
- dbmsg("open error");
- return -1;
- }
- dbmsg("arg=%s", arg);
- write(fd, arg, 1);
- return 0;
- }
-
- int main ( int argc, char *argv[] )
- {
- int ret;
- int num;
- int fd_gpio;
- if(argc < 2)
- {
- usage();
- return -1;
- }
-
- if(strncmp(argv[1],POWER_ON, sizeof(POWER_ON)) == 0)
- {
- dbmsg("%s", POWER_ON);
- if(argc != 3)
- {
- usage();
- return -1;
- }
- power_on(argv[2]);
- }
![](https://i-blog.csdnimg.cn/blog_migrate/f5eb4426879d9c4b4b2deb15679e0746.png)