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 }; 90 91 static void faux_device_release(struct device *dev) 92 { 93 struct faux_object *faux_obj = to_faux_object(dev); 94 95 kfree(faux_obj); 96 } 97 98 /** 99 * faux_device_create_with_groups - Create and register with the driver 100 * core a faux device and populate the device with an initial 101 * set of sysfs attributes. 102 * @name: The name of the device we are adding, must be unique for 103 * all faux devices. 104 * @parent: Pointer to a potential parent struct device. If set to 105 * NULL, the device will be created in the "root" of the faux 106 * device tree in sysfs. 107 * @faux_ops: struct faux_device_ops that the new device will call back 108 * into, can be NULL. 109 * @groups: The set of sysfs attributes that will be created for this 110 * device when it is registered with the driver core. 111 * 112 * Create a new faux device and register it in the driver core properly. 113 * If present, callbacks in @faux_ops will be called with the device that 114 * for the caller to do something with at the proper time given the 115 * device's lifecycle. 116 * 117 * Note, when this function is called, the functions specified in struct 118 * faux_ops can be called before the function returns, so be prepared for 119 * everything to be properly initialized before that point in time. If the 120 * probe callback (if one is present) does NOT succeed, the creation of the 121 * device will fail and NULL will be returned. 122 * 123 * Return: 124 * * NULL if an error happened with creating the device 125 * * pointer to a valid struct faux_device that is registered with sysfs 126 */ 127 struct faux_device *faux_device_create_with_groups(const char *name, 128 struct device *parent, 129 const struct faux_device_ops *faux_ops, 130 const struct attribute_group **groups) 131 { 132 struct faux_object *faux_obj; 133 struct faux_device *faux_dev; 134 struct device *dev; 135 int ret; 136 137 faux_obj = kzalloc(sizeof(*faux_obj), GFP_KERNEL); 138 if (!faux_obj) 139 return NULL; 140 141 /* Save off the callbacks and groups so we can use them in the future */ 142 faux_obj->faux_ops = faux_ops; 143 faux_obj->groups = groups; 144 145 /* Initialize the device portion and register it with the driver core */ 146 faux_dev = &faux_obj->faux_dev; 147 dev = &faux_dev->dev; 148 149 device_initialize(dev); 150 dev->release = faux_device_release; 151 if (parent) 152 dev->parent = parent; 153 else 154 dev->parent = &faux_bus_root; 155 dev->bus = &faux_bus_type; 156 dev_set_name(dev, "%s", name); 157 158 ret = device_add(dev); 159 if (ret) { 160 pr_err("%s: device_add for faux device '%s' failed with %d\n", 161 __func__, name, ret); 162 put_device(dev); 163 return NULL; 164 } 165 166 /* 167 * Verify that we did bind the driver to the device (i.e. probe worked), 168 * if not, let's fail the creation as trying to guess if probe was 169 * successful is almost impossible to determine by the caller. 170 */ 171 if (!dev->driver) { 172 dev_err(dev, "probe did not succeed, tearing down the device\n"); 173 faux_device_destroy(faux_dev); 174 faux_dev = NULL; 175 } 176 177 return faux_dev; 178 } 179 EXPORT_SYMBOL_GPL(faux_device_create_with_groups); 180 181 /** 182 * faux_device_create - create and register with the driver core a faux device 183 * @name: The name of the device we are adding, must be unique for all 184 * faux devices. 185 * @parent: Pointer to a potential parent struct device. If set to 186 * NULL, the device will be created in the "root" of the faux 187 * device tree in sysfs. 188 * @faux_ops: struct faux_device_ops that the new device will call back 189 * into, can be NULL. 190 * 191 * Create a new faux device and register it in the driver core properly. 192 * If present, callbacks in @faux_ops will be called with the device that 193 * for the caller to do something with at the proper time given the 194 * device's lifecycle. 195 * 196 * Note, when this function is called, the functions specified in struct 197 * faux_ops can be called before the function returns, so be prepared for 198 * everything to be properly initialized before that point in time. 199 * 200 * Return: 201 * * NULL if an error happened with creating the device 202 * * pointer to a valid struct faux_device that is registered with sysfs 203 */ 204 struct faux_device *faux_device_create(const char *name, 205 struct device *parent, 206 const struct faux_device_ops *faux_ops) 207 { 208 return faux_device_create_with_groups(name, parent, faux_ops, NULL); 209 } 210 EXPORT_SYMBOL_GPL(faux_device_create); 211 212 /** 213 * faux_device_destroy - destroy a faux device 214 * @faux_dev: faux device to destroy 215 * 216 * Unregisters and cleans up a device that was created with a call to 217 * faux_device_create() 218 */ 219 void faux_device_destroy(struct faux_device *faux_dev) 220 { 221 struct device *dev = &faux_dev->dev; 222 223 if (!faux_dev) 224 return; 225 226 device_del(dev); 227 228 /* The final put_device() will clean up the memory we allocated for this device. */ 229 put_device(dev); 230 } 231 EXPORT_SYMBOL_GPL(faux_device_destroy); 232 233 int __init faux_bus_init(void) 234 { 235 int ret; 236 237 ret = device_register(&faux_bus_root); 238 if (ret) { 239 put_device(&faux_bus_root); 240 return ret; 241 } 242 243 ret = bus_register(&faux_bus_type); 244 if (ret) 245 goto error_bus; 246 247 ret = driver_register(&faux_driver); 248 if (ret) 249 goto error_driver; 250 251 return ret; 252 253 error_driver: 254 bus_unregister(&faux_bus_type); 255 256 error_bus: 257 device_unregister(&faux_bus_root); 258 return ret; 259 } 260