GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / staging / most / hdm-dim2 / dim2_sysfs.c
1 /*
2  * dim2_sysfs.c - MediaLB sysfs information
3  *
4  * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  * GNU General Public License for more details.
10  *
11  * This file is licensed under GPLv2.
12  */
13
14 /* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
15
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18 #include <linux/kernel.h>
19 #include "dim2_sysfs.h"
20
21 struct bus_attr {
22         struct attribute attr;
23         ssize_t (*show)(struct medialb_bus *bus, char *buf);
24         ssize_t (*store)(struct medialb_bus *bus, const char *buf,
25                          size_t count);
26 };
27
28 static ssize_t state_show(struct medialb_bus *bus, char *buf)
29 {
30         bool state = dim2_sysfs_get_state_cb();
31
32         return sprintf(buf, "%s\n", state ? "locked" : "");
33 }
34
35 static struct bus_attr state_attr = __ATTR_RO(state);
36
37 static struct attribute *bus_default_attrs[] = {
38         &state_attr.attr,
39         NULL,
40 };
41
42 static const struct attribute_group bus_attr_group = {
43         .attrs = bus_default_attrs,
44 };
45
46 static void bus_kobj_release(struct kobject *kobj)
47 {
48 }
49
50 static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
51                                   char *buf)
52 {
53         struct medialb_bus *bus =
54                 container_of(kobj, struct medialb_bus, kobj_group);
55         struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
56
57         if (!xattr->show)
58                 return -EIO;
59
60         return xattr->show(bus, buf);
61 }
62
63 static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
64                                    const char *buf, size_t count)
65 {
66         struct medialb_bus *bus =
67                 container_of(kobj, struct medialb_bus, kobj_group);
68         struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
69
70         if (!xattr->store)
71                 return -EIO;
72
73         return xattr->store(bus, buf, count);
74 }
75
76 static struct sysfs_ops const bus_kobj_sysfs_ops = {
77         .show = bus_kobj_attr_show,
78         .store = bus_kobj_attr_store,
79 };
80
81 static struct kobj_type bus_ktype = {
82         .release = bus_kobj_release,
83         .sysfs_ops = &bus_kobj_sysfs_ops,
84 };
85
86 int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
87 {
88         int err;
89
90         kobject_init(&bus->kobj_group, &bus_ktype);
91         err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
92         if (err) {
93                 pr_err("kobject_add() failed: %d\n", err);
94                 goto err_kobject_add;
95         }
96
97         err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
98         if (err) {
99                 pr_err("sysfs_create_group() failed: %d\n", err);
100                 goto err_create_group;
101         }
102
103         return 0;
104
105 err_create_group:
106         kobject_put(&bus->kobj_group);
107
108 err_kobject_add:
109         return err;
110 }
111
112 void dim2_sysfs_destroy(struct medialb_bus *bus)
113 {
114         kobject_put(&bus->kobj_group);
115 }