1 // SPDX-License-Identifier: GPL-2.0
3 * Fieldbus Device Driver Core
7 #include <linux/mutex.h>
8 #include <linux/module.h>
9 #include <linux/device.h>
10 #include <linux/idr.h>
12 #include <linux/slab.h>
13 #include <linux/poll.h>
15 /* move to <linux/fieldbus_dev.h> when taking this out of staging */
16 #include "fieldbus_dev.h"
18 /* Maximum number of fieldbus devices */
19 #define MAX_FIELDBUSES 32
21 /* the dev_t structure to store the dynamically allocated fieldbus devices */
22 static dev_t fieldbus_devt;
23 static DEFINE_IDA(fieldbus_ida);
24 static DEFINE_MUTEX(fieldbus_mtx);
26 static const char ctrl_enabled[] = "enabled";
27 static const char ctrl_disabled[] = "disabled";
29 static ssize_t online_show(struct device *dev, struct device_attribute *attr,
32 struct fieldbus_dev *fb = dev_get_drvdata(dev);
34 return sprintf(buf, "%d\n", !!fb->online);
36 static DEVICE_ATTR_RO(online);
38 static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
41 struct fieldbus_dev *fb = dev_get_drvdata(dev);
45 return sprintf(buf, "%d\n", !!fb->enable_get(fb));
48 static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
49 const char *buf, size_t n)
51 struct fieldbus_dev *fb = dev_get_drvdata(dev);
55 if (!fb->simple_enable_set)
57 ret = kstrtobool(buf, &value);
60 ret = fb->simple_enable_set(fb, value);
65 static DEVICE_ATTR_RW(enabled);
67 static ssize_t card_name_show(struct device *dev, struct device_attribute *attr,
70 struct fieldbus_dev *fb = dev_get_drvdata(dev);
73 * card_name was provided by child driver, could potentially be long.
74 * protect against buffer overrun.
76 return snprintf(buf, PAGE_SIZE, "%s\n", fb->card_name);
78 static DEVICE_ATTR_RO(card_name);
80 static ssize_t read_area_size_show(struct device *dev,
81 struct device_attribute *attr, char *buf)
83 struct fieldbus_dev *fb = dev_get_drvdata(dev);
85 return sprintf(buf, "%zu\n", fb->read_area_sz);
87 static DEVICE_ATTR_RO(read_area_size);
89 static ssize_t write_area_size_show(struct device *dev,
90 struct device_attribute *attr, char *buf)
92 struct fieldbus_dev *fb = dev_get_drvdata(dev);
94 return sprintf(buf, "%zu\n", fb->write_area_sz);
96 static DEVICE_ATTR_RO(write_area_size);
98 static ssize_t fieldbus_id_show(struct device *dev,
99 struct device_attribute *attr, char *buf)
101 struct fieldbus_dev *fb = dev_get_drvdata(dev);
103 return fb->fieldbus_id_get(fb, buf, PAGE_SIZE);
105 static DEVICE_ATTR_RO(fieldbus_id);
107 static ssize_t fieldbus_type_show(struct device *dev,
108 struct device_attribute *attr, char *buf)
110 struct fieldbus_dev *fb = dev_get_drvdata(dev);
113 switch (fb->fieldbus_type) {
114 case FIELDBUS_DEV_TYPE_PROFINET:
122 return sprintf(buf, "%s\n", t);
124 static DEVICE_ATTR_RO(fieldbus_type);
126 static struct attribute *fieldbus_attrs[] = {
127 &dev_attr_enabled.attr,
128 &dev_attr_card_name.attr,
129 &dev_attr_fieldbus_id.attr,
130 &dev_attr_read_area_size.attr,
131 &dev_attr_write_area_size.attr,
132 &dev_attr_online.attr,
133 &dev_attr_fieldbus_type.attr,
137 static umode_t fieldbus_is_visible(struct kobject *kobj, struct attribute *attr,
140 struct device *dev = container_of(kobj, struct device, kobj);
141 struct fieldbus_dev *fb = dev_get_drvdata(dev);
142 umode_t mode = attr->mode;
144 if (attr == &dev_attr_enabled.attr) {
148 if (fb->simple_enable_set)
155 static const struct attribute_group fieldbus_group = {
156 .attrs = fieldbus_attrs,
157 .is_visible = fieldbus_is_visible,
159 __ATTRIBUTE_GROUPS(fieldbus);
161 static struct class fieldbus_class = {
162 .name = "fieldbus_dev",
163 .owner = THIS_MODULE,
164 .dev_groups = fieldbus_groups,
167 struct fb_open_file {
168 struct fieldbus_dev *fbdev;
172 static int fieldbus_open(struct inode *inode, struct file *filp)
174 struct fb_open_file *of;
175 struct fieldbus_dev *fbdev = container_of(inode->i_cdev,
179 of = kzalloc(sizeof(*of), GFP_KERNEL);
183 filp->private_data = of;
187 static int fieldbus_release(struct inode *node, struct file *filp)
189 struct fb_open_file *of = filp->private_data;
195 static ssize_t fieldbus_read(struct file *filp, char __user *buf, size_t size,
198 struct fb_open_file *of = filp->private_data;
199 struct fieldbus_dev *fbdev = of->fbdev;
201 of->dc_event = fbdev->dc_event;
202 return fbdev->read_area(fbdev, buf, size, offset);
205 static ssize_t fieldbus_write(struct file *filp, const char __user *buf,
206 size_t size, loff_t *offset)
208 struct fb_open_file *of = filp->private_data;
209 struct fieldbus_dev *fbdev = of->fbdev;
211 return fbdev->write_area(fbdev, buf, size, offset);
214 static __poll_t fieldbus_poll(struct file *filp, poll_table *wait)
216 struct fb_open_file *of = filp->private_data;
217 struct fieldbus_dev *fbdev = of->fbdev;
218 __poll_t mask = EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM;
220 poll_wait(filp, &fbdev->dc_wq, wait);
222 if (fbdev->dc_event != of->dc_event)
223 mask |= EPOLLPRI | EPOLLERR;
227 static const struct file_operations fieldbus_fops = {
228 .open = fieldbus_open,
229 .release = fieldbus_release,
230 .read = fieldbus_read,
231 .write = fieldbus_write,
232 .poll = fieldbus_poll,
233 .llseek = generic_file_llseek,
234 .owner = THIS_MODULE,
237 void fieldbus_dev_area_updated(struct fieldbus_dev *fb)
240 wake_up_all(&fb->dc_wq);
242 EXPORT_SYMBOL_GPL(fieldbus_dev_area_updated);
244 void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online)
247 kobject_uevent(&fb->dev->kobj, KOBJ_CHANGE);
249 EXPORT_SYMBOL_GPL(fieldbus_dev_online_changed);
251 static void __fieldbus_dev_unregister(struct fieldbus_dev *fb)
255 device_destroy(&fieldbus_class, fb->cdev.dev);
257 ida_simple_remove(&fieldbus_ida, fb->id);
260 void fieldbus_dev_unregister(struct fieldbus_dev *fb)
262 mutex_lock(&fieldbus_mtx);
263 __fieldbus_dev_unregister(fb);
264 mutex_unlock(&fieldbus_mtx);
266 EXPORT_SYMBOL_GPL(fieldbus_dev_unregister);
268 static int __fieldbus_dev_register(struct fieldbus_dev *fb)
275 if (!fb->read_area || !fb->write_area || !fb->fieldbus_id_get)
277 fb->id = ida_simple_get(&fieldbus_ida, 0, MAX_FIELDBUSES, GFP_KERNEL);
280 devno = MKDEV(MAJOR(fieldbus_devt), fb->id);
281 init_waitqueue_head(&fb->dc_wq);
282 cdev_init(&fb->cdev, &fieldbus_fops);
283 err = cdev_add(&fb->cdev, devno, 1);
285 pr_err("fieldbus_dev%d unable to add device %d:%d\n",
286 fb->id, MAJOR(fieldbus_devt), fb->id);
289 fb->dev = device_create(&fieldbus_class, fb->parent, devno, fb,
290 "fieldbus_dev%d", fb->id);
291 if (IS_ERR(fb->dev)) {
292 err = PTR_ERR(fb->dev);
300 ida_simple_remove(&fieldbus_ida, fb->id);
304 int fieldbus_dev_register(struct fieldbus_dev *fb)
308 mutex_lock(&fieldbus_mtx);
309 err = __fieldbus_dev_register(fb);
310 mutex_unlock(&fieldbus_mtx);
314 EXPORT_SYMBOL_GPL(fieldbus_dev_register);
316 static int __init fieldbus_init(void)
320 err = class_register(&fieldbus_class);
322 pr_err("fieldbus_dev: could not register class\n");
325 err = alloc_chrdev_region(&fieldbus_devt, 0,
326 MAX_FIELDBUSES, "fieldbus_dev");
328 pr_err("fieldbus_dev: unable to allocate char dev region\n");
334 class_unregister(&fieldbus_class);
338 static void __exit fieldbus_exit(void)
340 unregister_chrdev_region(fieldbus_devt, MAX_FIELDBUSES);
341 class_unregister(&fieldbus_class);
342 ida_destroy(&fieldbus_ida);
345 subsys_initcall(fieldbus_init);
346 module_exit(fieldbus_exit);
348 MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
349 MODULE_AUTHOR("Jonathan Stiles <jonathans@arcx.com>");
350 MODULE_DESCRIPTION("Fieldbus Device Driver Core");
351 MODULE_LICENSE("GPL v2");