linux/samples/firmware_class/firmware_sample_firmware_class.c
<<
>>
Prefs
   1/*
   2 * firmware_sample_firmware_class.c -
   3 *
   4 * Copyright (c) 2003 Manuel Estrada Sainz
   5 *
   6 * NOTE: This is just a probe of concept, if you think that your driver would
   7 * be well served by this mechanism please contact me first.
   8 *
   9 * DON'T USE THIS CODE AS IS
  10 *
  11 */
  12
  13#include <linux/device.h>
  14#include <linux/module.h>
  15#include <linux/init.h>
  16#include <linux/timer.h>
  17#include <linux/slab.h>
  18#include <linux/string.h>
  19#include <linux/firmware.h>
  20
  21
  22MODULE_AUTHOR("Manuel Estrada Sainz");
  23MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
  24MODULE_LICENSE("GPL");
  25
  26static inline struct class_device *to_class_dev(struct kobject *obj)
  27{
  28        return container_of(obj, struct class_device, kobj);
  29}
  30
  31static inline
  32struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
  33{
  34        return container_of(_attr, struct class_device_attribute, attr);
  35}
  36
  37struct firmware_priv {
  38        char fw_id[FIRMWARE_NAME_MAX];
  39        s32 loading:2;
  40        u32 abort:1;
  41};
  42
  43static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
  44{
  45        struct firmware_priv *fw_priv = class_get_devdata(class_dev);
  46        return sprintf(buf, "%d\n", fw_priv->loading);
  47}
  48
  49static ssize_t firmware_loading_store(struct class_device *class_dev,
  50                                      const char *buf, size_t count)
  51{
  52        struct firmware_priv *fw_priv = class_get_devdata(class_dev);
  53        int prev_loading = fw_priv->loading;
  54
  55        fw_priv->loading = simple_strtol(buf, NULL, 10);
  56
  57        switch (fw_priv->loading) {
  58        case -1:
  59                /* abort load an panic */
  60                break;
  61        case 1:
  62                /* setup load */
  63                break;
  64        case 0:
  65                if (prev_loading == 1) {
  66                        /* finish load and get the device back to working
  67                         * state */
  68                }
  69                break;
  70        }
  71
  72        return count;
  73}
  74static CLASS_DEVICE_ATTR(loading, 0644,
  75                         firmware_loading_show, firmware_loading_store);
  76
  77static ssize_t firmware_data_read(struct kobject *kobj,
  78                                  struct bin_attribute *bin_attr,
  79                                  char *buffer, loff_t offset, size_t count)
  80{
  81        struct class_device *class_dev = to_class_dev(kobj);
  82        struct firmware_priv *fw_priv = class_get_devdata(class_dev);
  83
  84        /* read from the devices firmware memory */
  85
  86        return count;
  87}
  88static ssize_t firmware_data_write(struct kobject *kobj,
  89                                   struct bin_attribute *bin_attr,
  90                                   char *buffer, loff_t offset, size_t count)
  91{
  92        struct class_device *class_dev = to_class_dev(kobj);
  93        struct firmware_priv *fw_priv = class_get_devdata(class_dev);
  94
  95        /* write to the devices firmware memory */
  96
  97        return count;
  98}
  99static struct bin_attribute firmware_attr_data = {
 100        .attr = {.name = "data", .mode = 0644},
 101        .size = 0,
 102        .read = firmware_data_read,
 103        .write = firmware_data_write,
 104};
 105static int fw_setup_class_device(struct class_device *class_dev,
 106                                 const char *fw_name,
 107                                 struct device *device)
 108{
 109        int retval;
 110        struct firmware_priv *fw_priv;
 111
 112        fw_priv = kzalloc(sizeof(struct firmware_priv), GFP_KERNEL);
 113        if (!fw_priv) {
 114                retval = -ENOMEM;
 115                goto out;
 116        }
 117
 118        memset(class_dev, 0, sizeof(*class_dev));
 119
 120        strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
 121        fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
 122
 123        strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
 124        class_dev->class_id[BUS_ID_SIZE-1] = '\0';
 125        class_dev->dev = device;
 126
 127        class_dev->class = &firmware_class;
 128        class_set_devdata(class_dev, fw_priv);
 129        retval = class_device_register(class_dev);
 130        if (retval) {
 131                printk(KERN_ERR "%s: class_device_register failed\n",
 132                       __func__);
 133                goto error_free_fw_priv;
 134        }
 135
 136        retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
 137        if (retval) {
 138                printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
 139                       __func__);
 140                goto error_unreg_class_dev;
 141        }
 142
 143        retval = class_device_create_file(class_dev,
 144                                          &class_device_attr_loading);
 145        if (retval) {
 146                printk(KERN_ERR "%s: class_device_create_file failed\n",
 147                       __func__);
 148                goto error_remove_data;
 149        }
 150
 151        goto out;
 152
 153error_remove_data:
 154        sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
 155error_unreg_class_dev:
 156        class_device_unregister(class_dev);
 157error_free_fw_priv:
 158        kfree(fw_priv);
 159out:
 160        return retval;
 161}
 162static void fw_remove_class_device(struct class_device *class_dev)
 163{
 164        struct firmware_priv *fw_priv = class_get_devdata(class_dev);
 165
 166        class_device_remove_file(class_dev, &class_device_attr_loading);
 167        sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
 168        class_device_unregister(class_dev);
 169}
 170
 171static struct class_device *class_dev;
 172
 173static struct device my_device = {
 174        .bus_id    = "my_dev0",
 175};
 176
 177static int __init firmware_sample_init(void)
 178{
 179        int error;
 180
 181        device_initialize(&my_device);
 182        class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
 183        if (!class_dev)
 184                return -ENOMEM;
 185
 186        error = fw_setup_class_device(class_dev, "my_firmware_image",
 187                                      &my_device);
 188        if (error) {
 189                kfree(class_dev);
 190                return error;
 191        }
 192        return 0;
 193
 194}
 195static void __exit firmware_sample_exit(void)
 196{
 197        struct firmware_priv *fw_priv = class_get_devdata(class_dev);
 198        fw_remove_class_device(class_dev);
 199        kfree(fw_priv);
 200        kfree(class_dev);
 201}
 202
 203module_init(firmware_sample_init);
 204module_exit(firmware_sample_exit);
 205