1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2025 Greg Kroah-Hartman <gregkh@linuxfoundation.org> 4 * Copyright (c) 2025 The Linux Foundation 5 * 6 * A "simple" faux bus that allows devices to be created and added 7 * automatically to it. This is to be used whenever you need to create a 8 * device that is not associated with any "real" system resources, and do 9 * not want to have to deal with a bus/driver binding logic. It is 10 * intended to be very simple, with only a create and a destroy function 11 * available. 12 */ 13 #include <linux/err.h> 14 #include <linux/init.h> 15 #include <linux/slab.h> 16 #include <linux/string.h> 17 #include <linux/container_of.h> 18 #include <linux/device/faux.h> 19 #include "base.h" 20 21 /* 22 * Internal wrapper structure so we can hold a pointer to the 23 * faux_device_ops for this device. 24 */ 25 struct faux_object { 26 struct faux_device faux_dev; 27 const struct faux_device_ops *faux_ops; 28 const struct attribute_group **groups; 29 }; 30 #define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev) 31 32 static struct device faux_bus_root = { 33 .init_name = "faux", 34 }; 35 36 static int faux_match(struct device *dev, const struct device_driver *drv) 37 { 38 /* Match always succeeds, we only have one driver */ 39 return 1; 40 } 41 42 static int faux_probe(struct device *dev) 43 { 44 struct faux_object *faux_obj = to_faux_object(dev); 45 struct faux_device *faux_dev = &faux_obj->faux_dev; 46 const struct faux_device_ops *faux_ops = faux_obj->faux_ops; 47 int ret; 48 49 if (faux_ops && faux_ops->probe) { 50 ret = faux_ops->probe(faux_dev); 51 if (ret) 52 return ret; 53 } 54 55 /* 56 * Add groups after the probe succeeds to ensure resources are 57 * initialized correctly 58 */ 59 ret = device_add_groups(dev, faux_obj->groups); 60 if (ret && faux_ops && faux_ops->remove) 61 faux_ops->remove(faux_dev); 62 63 return ret; 64 } 65 66 static void faux_remove(struct device *dev) 67 { 68 struct faux_object *faux_obj = to_faux_object(dev); 69 struct faux_device *faux_dev = &faux_obj->faux_dev; 70 const struct faux_device_ops *faux_ops = faux_obj->faux_ops; 71 72 device_remove_groups(dev, faux_obj->groups); 73 74 if (faux_ops && faux_ops->remove) 75 faux_ops->remove(faux_dev); 76 } 77 78 static const struct bus_type faux_bus_type = { 79 .name = "faux", 80 .match = faux_match, 81 .probe = faux_probe, 82 .remove = faux_remove, 83 }; 84 85 static struct device_driver faux_driver = { 86 .name = "faux_driver", 87 .bus = &faux_bus_type, 88 .probe_type = PROBE_FORCE_SYNCHRONOUS, 89 .suppress_bind_attrs = true, 90 }; 91 92 static void faux_device_release(struct device *dev) 93 { 94 struct faux_object *faux_obj = to_faux_object(dev); 95 96 kfree(faux_obj); 97 } 98 99 /** 100 * faux_device_create_with_groups - Create and register with the driver 101 * core a faux device and populate the device with an initial 102 * set of sysfs attributes. 103 * @name: The name of the device we are adding, must be unique for 104 * all faux devices. 105 * @parent: Pointer to a potential parent struct device. If set to 106 * NULL, the device will be created in the "root" of the faux 107 * device tree in sysfs. 108 * @faux_ops: struct faux_device_ops that the new device will call back 109 * into, can be NULL. 110 * @groups: The set of sysfs attributes that will be created for this 111 * device when it is registered with the driver core. 112 * 113 * Create a new faux device and register it in the driver core properly. 114 * If present, callbacks in @faux_ops will be called with the device that 115 * for the caller to do something with at the proper time given the 116 * device's lifecycle. 117 * 118 * Note, when this function is called, the functions specified in struct 119 * faux_ops can be called before the function returns, so be prepared for 120 * everything to be properly initialized before that point in time. If the 121 * probe callback (if one is present) does NOT succeed, the creation of the 122 * device will fail and NULL will be returned. 123 * 124 * Return: 125 * * NULL if an error happened with creating the device 126 * * pointer to a valid struct faux_device that is registered with sysfs 127 */ 128 struct faux_device *faux_device_create_with_groups(const char *name, 129 struct device *parent, 130 const struct faux_device_ops *faux_ops, 131 const struct attribute_group **groups) 132 { 133 struct faux_object *faux_obj; 134 struct faux_device *faux_dev; 135 struct device *dev; 136 int ret; 137 138 faux_obj = kzalloc(sizeof(*faux_obj), GFP_KERNEL); 139 if (!faux_obj) 140 return NULL; 141 142 /* Save off the callbacks and groups so we can use them in the future */ 143 faux_obj->faux_ops = faux_ops; 144 faux_obj->groups = groups; 145 146 /* Initialize the device portion and register it with the driver core */ 147 faux_dev = &faux_obj->faux_dev; 148 dev = &faux_dev->dev; 149 150 device_initialize(dev); 151 dev->release = faux_device_release; 152 if (parent) 153 dev->parent = parent; 154 else 155 dev->parent = &faux_bus_root; 156 dev->bus = &faux_bus_type; 157 dev_set_name(dev, "%s", name); 158 159 ret = device_add(dev); 160 if (ret) { 161 pr_err("%s: device_add for faux device '%s' failed with %d\n", 162 __func__, name, ret); 163 put_device(dev); 164 return NULL; 165 } 166 167 /* 168 * Verify that we did bind the driver to the device (i.e. probe worked), 169 * if not, let's fail the creation as trying to guess if probe was 170 * successful is almost impossible to determine by the caller. 171 */ 172 if (!dev->driver) { 173 dev_dbg(dev, "probe did not succeed, tearing down the device\n"); 174 faux_device_destroy(faux_dev); 175 faux_dev = NULL; 176 } 177 178 return faux_dev; 179 } 180 EXPORT_SYMBOL_GPL(faux_device_create_with_groups); 181 182 /** 183 * faux_device_create - create and register with the driver core a faux device 184 * @name: The name of the device we are adding, must be unique for all 185 * faux devices. 186 * @parent: Pointer to a potential parent struct device. If set to 187 * NULL, the device will be created in the "root" of the faux 188 * device tree in sysfs. 189 * @faux_ops: struct faux_device_ops that the new device will call back 190 * into, can be NULL. 191 * 192 * Create a new faux device and register it in the driver core properly. 193 * If present, callbacks in @faux_ops will be called with the device that 194 * for the caller to do something with at the proper time given the 195 * device's lifecycle. 196 * 197 * Note, when this function is called, the functions specified in struct 198 * faux_ops can be called before the function returns, so be prepared for 199 * everything to be properly initialized before that point in time. 200 * 201 * Return: 202 * * NULL if an error happened with creating the device 203 * * pointer to a valid struct faux_device that is registered with sysfs 204 */ 205 struct faux_device *faux_device_create(const char *name, 206 struct device *parent, 207 const struct faux_device_ops *faux_ops) 208 { 209 return faux_device_create_with_groups(name, parent, faux_ops, NULL); 210 } 211 EXPORT_SYMBOL_GPL(faux_device_create); 212 213 /** 214 * faux_device_destroy - destroy a faux device 215 * @faux_dev: faux device to destroy 216 * 217 * Unregisters and cleans up a device that was created with a call to 218 * faux_device_create() 219 */ 220 void faux_device_destroy(struct faux_device *faux_dev) 221 { 222 struct device *dev = &faux_dev->dev; 223 224 if (!faux_dev) 225 return; 226 227 device_del(dev); 228 229 /* The final put_device() will clean up the memory we allocated for this device. */ 230 put_device(dev); 231 } 232 EXPORT_SYMBOL_GPL(faux_device_destroy); 233 234 int __init faux_bus_init(void) 235 { 236 int ret; 237 238 ret = device_register(&faux_bus_root); 239 if (ret) { 240 put_device(&faux_bus_root); 241 return ret; 242 } 243 244 ret = bus_register(&faux_bus_type); 245 if (ret) 246 goto error_bus; 247 248 ret = driver_register(&faux_driver); 249 if (ret) 250 goto error_driver; 251 252 return ret; 253 254 error_driver: 255 bus_unregister(&faux_bus_type); 256 257 error_bus: 258 device_unregister(&faux_bus_root); 259 return ret; 260 } 261