• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/linux/linux-2.6/Documentation/firmware_class/
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}
30static inline
31struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
32{
33	return container_of(_attr,struct class_device_attribute,attr);
34}
35
36int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
37int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
38
39struct firmware_priv {
40	char fw_id[FIRMWARE_NAME_MAX];
41	s32 loading:2;
42	u32 abort:1;
43};
44
45extern struct class firmware_class;
46
47static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
48{
49	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
50	return sprintf(buf, "%d\n", fw_priv->loading);
51}
52static ssize_t firmware_loading_store(struct class_device *class_dev,
53				      const char *buf, size_t count)
54{
55	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
56	int prev_loading = fw_priv->loading;
57
58	fw_priv->loading = simple_strtol(buf, NULL, 10);
59
60	switch(fw_priv->loading){
61	case -1:
62		/* abort load an panic */
63		break;
64	case 1:
65		/* setup load */
66		break;
67	case 0:
68		if(prev_loading==1){
69			/* finish load and get the device back to working
70			 * state */
71		}
72		break;
73	}
74
75	return count;
76}
77static CLASS_DEVICE_ATTR(loading, 0644,
78			 firmware_loading_show, firmware_loading_store);
79
80static ssize_t firmware_data_read(struct kobject *kobj,
81				  char *buffer, loff_t offset, size_t count)
82{
83	struct class_device *class_dev = to_class_dev(kobj);
84	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
85
86	/* read from the devices firmware memory */
87
88	return count;
89}
90static ssize_t firmware_data_write(struct kobject *kobj,
91				   char *buffer, loff_t offset, size_t count)
92{
93	struct class_device *class_dev = to_class_dev(kobj);
94	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
95
96	/* write to the devices firmware memory */
97
98	return count;
99}
100static struct bin_attribute firmware_attr_data = {
101	.attr = {.name = "data", .mode = 0644},
102	.size = 0,
103	.read = firmware_data_read,
104	.write = firmware_data_write,
105};
106static int fw_setup_class_device(struct class_device *class_dev,
107				 const char *fw_name,
108				 struct device *device)
109{
110	int retval = 0;
111	struct firmware_priv *fw_priv = kmalloc(sizeof(struct firmware_priv),
112						GFP_KERNEL);
113
114	if(!fw_priv){
115		retval = -ENOMEM;
116		goto out;
117	}
118	memset(fw_priv, 0, sizeof(*fw_priv));
119	memset(class_dev, 0, sizeof(*class_dev));
120
121	strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
122	fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
123
124	strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
125	class_dev->class_id[BUS_ID_SIZE-1] = '\0';
126	class_dev->dev = device;
127
128	class_dev->class = &firmware_class,
129	class_set_devdata(class_dev, fw_priv);
130	retval = class_device_register(class_dev);
131	if (retval){
132		printk(KERN_ERR "%s: class_device_register failed\n",
133		       __FUNCTION__);
134		goto error_free_fw_priv;
135	}
136
137	retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
138	if (retval){
139		printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
140		       __FUNCTION__);
141		goto error_unreg_class_dev;
142	}
143
144	retval = class_device_create_file(class_dev,
145					  &class_device_attr_loading);
146	if (retval){
147		printk(KERN_ERR "%s: class_device_create_file failed\n",
148		       __FUNCTION__);
149		goto error_remove_data;
150	}
151
152	goto out;
153
154error_remove_data:
155	sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
156error_unreg_class_dev:
157	class_device_unregister(class_dev);
158error_free_fw_priv:
159	kfree(fw_priv);
160out:
161	return retval;
162}
163static void fw_remove_class_device(struct class_device *class_dev)
164{
165	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
166
167	class_device_remove_file(class_dev, &class_device_attr_loading);
168	sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
169	class_device_unregister(class_dev);
170}
171
172static struct class_device *class_dev;
173
174static struct device my_device = {
175	.bus_id    = "my_dev0",
176};
177
178static int __init firmware_sample_init(void)
179{
180	int error;
181
182	device_initialize(&my_device);
183	class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
184	if(!class_dev)
185		return -ENOMEM;
186
187	error = fw_setup_class_device(class_dev, "my_firmware_image",
188				      &my_device);
189	if(error){
190		kfree(class_dev);
191		return error;
192	}
193        return 0;
194
195}
196static void __exit firmware_sample_exit(void)
197{
198	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
199	fw_remove_class_device(class_dev);
200	kfree(fw_priv);
201	kfree(class_dev);
202}
203module_init(firmware_sample_init);
204module_exit(firmware_sample_exit);
205