linux/drivers/base/class_simple.c
<<
>>
Prefs
   1/*
   2 * class_simple.c - a "simple" interface for classes for simple char devices.
   3 *
   4 * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
   5 * Copyright (c) 2003-2004 IBM Corp.
   6 *
   7 * This file is released under the GPLv2
   8 *
   9 */
  10
  11#include <linux/config.h>
  12#include <linux/device.h>
  13#include <linux/kdev_t.h>
  14#include <linux/err.h>
  15
  16struct class_simple {
  17        struct class_device_attribute attr;
  18        struct class class;
  19};
  20#define to_class_simple(d) container_of(d, struct class_simple, class)
  21
  22struct simple_dev {
  23        struct list_head node;
  24        dev_t dev;
  25        struct class_device class_dev;
  26};
  27#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
  28
  29static LIST_HEAD(simple_dev_list);
  30static DEFINE_SPINLOCK(simple_dev_list_lock);
  31
  32static void release_simple_dev(struct class_device *class_dev)
  33{
  34        struct simple_dev *s_dev = to_simple_dev(class_dev);
  35        kfree(s_dev);
  36}
  37
  38static ssize_t show_dev(struct class_device *class_dev, char *buf)
  39{
  40        struct simple_dev *s_dev = to_simple_dev(class_dev);
  41        return print_dev_t(buf, s_dev->dev);
  42}
  43
  44static void class_simple_release(struct class *class)
  45{
  46        struct class_simple *cs = to_class_simple(class);
  47        kfree(cs);
  48}
  49
  50/**
  51 * class_simple_create - create a struct class_simple structure
  52 * @owner: pointer to the module that is to "own" this struct class_simple
  53 * @name: pointer to a string for the name of this class.
  54 *
  55 * This is used to create a struct class_simple pointer that can then be used
  56 * in calls to class_simple_device_add().  This is used when you do not wish to
  57 * create a full blown class support for a type of char devices.
  58 *
  59 * Note, the pointer created here is to be destroyed when finished by making a
  60 * call to class_simple_destroy().
  61 */
  62struct class_simple *class_simple_create(struct module *owner, char *name)
  63{
  64        struct class_simple *cs;
  65        int retval;
  66
  67        cs = kmalloc(sizeof(*cs), GFP_KERNEL);
  68        if (!cs) {
  69                retval = -ENOMEM;
  70                goto error;
  71        }
  72        memset(cs, 0x00, sizeof(*cs));
  73
  74        cs->class.name = name;
  75        cs->class.class_release = class_simple_release;
  76        cs->class.release = release_simple_dev;
  77
  78        cs->attr.attr.name = "dev";
  79        cs->attr.attr.mode = S_IRUGO;
  80        cs->attr.attr.owner = owner;
  81        cs->attr.show = show_dev;
  82        cs->attr.store = NULL;
  83
  84        retval = class_register(&cs->class);
  85        if (retval)
  86                goto error;
  87
  88        return cs;
  89
  90error:
  91        kfree(cs);
  92        return ERR_PTR(retval);
  93}
  94EXPORT_SYMBOL(class_simple_create);
  95
  96/**
  97 * class_simple_destroy - destroys a struct class_simple structure
  98 * @cs: pointer to the struct class_simple that is to be destroyed
  99 *
 100 * Note, the pointer to be destroyed must have been created with a call to
 101 * class_simple_create().
 102 */
 103void class_simple_destroy(struct class_simple *cs)
 104{
 105        if ((cs == NULL) || (IS_ERR(cs)))
 106                return;
 107
 108        class_unregister(&cs->class);
 109}
 110EXPORT_SYMBOL(class_simple_destroy);
 111
 112/**
 113 * class_simple_device_add - adds a class device to sysfs for a character driver
 114 * @cs: pointer to the struct class_simple that this device should be registered to.
 115 * @dev: the dev_t for the device to be added.
 116 * @device: a pointer to a struct device that is assiociated with this class device.
 117 * @fmt: string for the class device's name
 118 *
 119 * This function can be used by simple char device classes that do not
 120 * implement their own class device registration.  A struct class_device will
 121 * be created in sysfs, registered to the specified class.  A "dev" file will
 122 * be created, showing the dev_t for the device.  The pointer to the struct
 123 * class_device will be returned from the call.  Any further sysfs files that
 124 * might be required can be created using this pointer.
 125 * Note: the struct class_simple passed to this function must have previously been
 126 * created with a call to class_simple_create().
 127 */
 128struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
 129{
 130        va_list args;
 131        struct simple_dev *s_dev = NULL;
 132        int retval;
 133
 134        if ((cs == NULL) || (IS_ERR(cs))) {
 135                retval = -ENODEV;
 136                goto error;
 137        }
 138
 139        s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
 140        if (!s_dev) {
 141                retval = -ENOMEM;
 142                goto error;
 143        }
 144        memset(s_dev, 0x00, sizeof(*s_dev));
 145
 146        s_dev->dev = dev;
 147        s_dev->class_dev.dev = device;
 148        s_dev->class_dev.class = &cs->class;
 149
 150        va_start(args, fmt);
 151        vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
 152        va_end(args);
 153        retval = class_device_register(&s_dev->class_dev);
 154        if (retval)
 155                goto error;
 156
 157        class_device_create_file(&s_dev->class_dev, &cs->attr);
 158
 159        spin_lock(&simple_dev_list_lock);
 160        list_add(&s_dev->node, &simple_dev_list);
 161        spin_unlock(&simple_dev_list_lock);
 162
 163        return &s_dev->class_dev;
 164
 165error:
 166        kfree(s_dev);
 167        return ERR_PTR(retval);
 168}
 169EXPORT_SYMBOL(class_simple_device_add);
 170
 171/**
 172 * class_simple_set_hotplug - set the hotplug callback in the embedded struct class
 173 * @cs: pointer to the struct class_simple to hold the pointer
 174 * @hotplug: function pointer to the hotplug function
 175 *
 176 * Implement and set a hotplug function to add environment variables specific to this
 177 * class on the hotplug event.
 178 */
 179int class_simple_set_hotplug(struct class_simple *cs,
 180        int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
 181{
 182        if ((cs == NULL) || (IS_ERR(cs)))
 183                return -ENODEV;
 184        cs->class.hotplug = hotplug;
 185        return 0;
 186}
 187EXPORT_SYMBOL(class_simple_set_hotplug);
 188
 189/**
 190 * class_simple_device_remove - removes a class device that was created with class_simple_device_add()
 191 * @dev: the dev_t of the device that was previously registered.
 192 *
 193 * This call unregisters and cleans up a class device that was created with a
 194 * call to class_device_simple_add()
 195 */
 196void class_simple_device_remove(dev_t dev)
 197{
 198        struct simple_dev *s_dev = NULL;
 199        int found = 0;
 200
 201        spin_lock(&simple_dev_list_lock);
 202        list_for_each_entry(s_dev, &simple_dev_list, node) {
 203                if (s_dev->dev == dev) {
 204                        found = 1;
 205                        break;
 206                }
 207        }
 208        if (found) {
 209                list_del(&s_dev->node);
 210                spin_unlock(&simple_dev_list_lock);
 211                class_device_unregister(&s_dev->class_dev);
 212        } else {
 213                spin_unlock(&simple_dev_list_lock);
 214        }
 215}
 216EXPORT_SYMBOL(class_simple_device_remove);
 217
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.