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