1 /* Copyright © 2010 - 2013 UNISYS CORPORATION
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at
7 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12 * NON INFRINGEMENT. See the GNU General Public License for more
16 /** @file *********************************************************************
18 * Handle procfs-specific tasks.
19 * Note that this file does not know about any module-specific things, nor
20 * does it know anything about what information to reveal as part of the proc
21 * entries. The 2 functions that take care of displaying device and
22 * driver specific information are passed as parameters to
23 * visor_easyproc_InitDriver().
25 * void show_device_info(struct seq_file *seq, void *p);
26 * void show_driver_info(struct seq_file *seq);
28 * The second parameter to show_device_info is actually a pointer to the
29 * device-specific info to show. It is the context that was originally
30 * passed to visor_easyproc_InitDevice().
32 ******************************************************************************
35 #include <linux/proc_fs.h>
41 #define MYDRVNAME "easyproc"
46 * /proc/<ProcId> ProcDir
47 * /proc/<ProcId>/driver ProcDriverDir
48 * /proc/<ProcId>/driver/diag ProcDriverDiagFile
49 * /proc/<ProcId>/device ProcDeviceDir
50 * /proc/<ProcId>/device/0 procDevicexDir
51 * /proc/<ProcId>/device/0/diag procDevicexDiagFile
55 static ssize_t proc_write_device(struct file *file, const char __user *buffer,
56 size_t count, loff_t *ppos);
57 static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
58 size_t count, loff_t *ppos);
60 static struct proc_dir_entry *
61 createProcDir(char *name, struct proc_dir_entry *parent)
63 struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
65 ERRDRV("failed to create /proc directory %s", name);
69 static int seq_show_driver(struct seq_file *seq, void *offset);
70 static int proc_open_driver(struct inode *inode, struct file *file)
72 return single_open(file, seq_show_driver, PDE_DATA(inode));
74 static const struct file_operations proc_fops_driver = {
75 .open = proc_open_driver,
77 .write = proc_write_driver,
79 .release = single_release,
82 static int seq_show_device(struct seq_file *seq, void *offset);
83 static int seq_show_device_property(struct seq_file *seq, void *offset);
84 static int proc_open_device(struct inode *inode, struct file *file)
86 return single_open(file, seq_show_device, PDE_DATA(inode));
88 static const struct file_operations proc_fops_device = {
89 .open = proc_open_device,
91 .write = proc_write_device,
93 .release = single_release,
95 static int proc_open_device_property(struct inode *inode, struct file *file)
97 return single_open(file, seq_show_device_property, PDE_DATA(inode));
99 static const struct file_operations proc_fops_device_property = {
100 .open = proc_open_device_property,
103 .release = single_release,
108 void visor_easyproc_InitDriver(struct easyproc_driver_info *pdriver,
110 void (*show_driver_info)(struct seq_file *),
111 void (*show_device_info)(struct seq_file *,
114 memset(pdriver, 0, sizeof(struct easyproc_driver_info));
115 pdriver->ProcId = procId;
116 if (pdriver->ProcId == NULL)
117 ERRDRV("ProcId cannot be NULL (trouble ahead)!");
118 pdriver->Show_driver_info = show_driver_info;
119 pdriver->Show_device_info = show_device_info;
120 if (pdriver->ProcDir == NULL)
121 pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
122 if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
123 pdriver->ProcDriverDir = createProcDir("driver",
125 if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
126 pdriver->ProcDeviceDir = createProcDir("device",
128 if ((pdriver->ProcDriverDir != NULL) &&
129 (pdriver->ProcDriverDiagFile == NULL)) {
130 pdriver->ProcDriverDiagFile =
131 proc_create_data("diag", 0,
132 pdriver->ProcDriverDir,
133 &proc_fops_driver, pdriver);
134 if (pdriver->ProcDriverDiagFile == NULL)
135 ERRDRV("failed to register /proc/%s/driver/diag entry",
139 EXPORT_SYMBOL_GPL(visor_easyproc_InitDriver);
143 void visor_easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
145 void (*show_driver_info)(struct seq_file *),
146 void (*show_device_info)(struct seq_file *,
148 void (*write_driver_info)(char *buf,
151 void (*write_device_info)(char *buf,
156 visor_easyproc_InitDriver(pdriver, procId,
157 show_driver_info, show_device_info);
158 pdriver->Write_driver_info = write_driver_info;
159 pdriver->Write_device_info = write_device_info;
161 EXPORT_SYMBOL_GPL(visor_easyproc_InitDriverEx);
165 void visor_easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
167 if (pdriver->ProcDriverDiagFile != NULL) {
168 remove_proc_entry("diag", pdriver->ProcDriverDir);
169 pdriver->ProcDriverDiagFile = NULL;
171 if (pdriver->ProcDriverDir != NULL) {
172 remove_proc_entry("driver", pdriver->ProcDir);
173 pdriver->ProcDriverDir = NULL;
175 if (pdriver->ProcDeviceDir != NULL) {
176 remove_proc_entry("device", pdriver->ProcDir);
177 pdriver->ProcDeviceDir = NULL;
179 if (pdriver->ProcDir != NULL) {
180 remove_proc_entry(pdriver->ProcId, NULL);
181 pdriver->ProcDir = NULL;
183 pdriver->ProcId = NULL;
184 pdriver->Show_driver_info = NULL;
185 pdriver->Show_device_info = NULL;
186 pdriver->Write_driver_info = NULL;
187 pdriver->Write_device_info = NULL;
189 EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDriver);
193 void visor_easyproc_InitDevice(struct easyproc_driver_info *pdriver,
194 struct easyproc_device_info *p, int devno,
197 if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
199 sprintf(s, "%d", devno);
200 p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
203 p->devdata = devdata;
204 p->pdriver = pdriver;
206 if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
207 p->procDevicexDiagFile =
208 proc_create_data("diag", 0, p->procDevicexDir,
209 &proc_fops_device, p);
210 if (p->procDevicexDiagFile == NULL)
211 ERRDEVX(devno, "failed to register /proc/%s/device/%d/diag entry",
212 pdriver->ProcId, devno
215 memset(&(p->device_property_info[0]), 0,
216 sizeof(p->device_property_info));
218 EXPORT_SYMBOL_GPL(visor_easyproc_InitDevice);
222 void visor_easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
223 void (*show_property_info)
224 (struct seq_file *, void *),
228 struct easyproc_device_property_info *px = NULL;
230 if (p->procDevicexDir == NULL) {
231 ERRDRV("state error");
234 for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
235 if (p->device_property_info[i].procEntry == NULL) {
236 px = &(p->device_property_info[i]);
241 ERRDEVX(p->devno, "too many device properties");
244 px->devdata = p->devdata;
245 px->pdriver = p->pdriver;
246 px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
247 &proc_fops_device_property, px);
248 if (strlen(property_name)+1 > sizeof(px->property_name)) {
249 ERRDEVX(p->devno, "device property name %s too long",
253 strcpy(px->property_name, property_name);
254 if (px->procEntry == NULL) {
255 ERRDEVX(p->devno, "failed to register /proc/%s/device/%d/%s entry",
256 p->pdriver->ProcId, p->devno, property_name
260 px->show_device_property_info = show_property_info;
262 EXPORT_SYMBOL_GPL(visor_easyproc_CreateDeviceProperty);
266 void visor_easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
267 struct easyproc_device_info *p, int devno)
270 for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
271 if (p->device_property_info[i].procEntry != NULL) {
272 struct easyproc_device_property_info *px =
273 &(p->device_property_info[i]);
274 remove_proc_entry(px->property_name, p->procDevicexDir);
275 px->procEntry = NULL;
278 if (p->procDevicexDiagFile != NULL) {
279 remove_proc_entry("diag", p->procDevicexDir);
280 p->procDevicexDiagFile = NULL;
282 if (p->procDevicexDir != NULL) {
284 sprintf(s, "%d", devno);
285 remove_proc_entry(s, pdriver->ProcDeviceDir);
286 p->procDevicexDir = NULL;
291 EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDevice);
295 static int seq_show_driver(struct seq_file *seq, void *offset)
297 struct easyproc_driver_info *p =
298 (struct easyproc_driver_info *)(seq->private);
301 (*(p->Show_driver_info))(seq);
307 static int seq_show_device(struct seq_file *seq, void *offset)
309 struct easyproc_device_info *p =
310 (struct easyproc_device_info *)(seq->private);
311 if ((!p) || (!(p->pdriver)))
313 (*(p->pdriver->Show_device_info))(seq, p->devdata);
319 static int seq_show_device_property(struct seq_file *seq, void *offset)
321 struct easyproc_device_property_info *p =
322 (struct easyproc_device_property_info *)(seq->private);
323 if ((!p) || (!(p->show_device_property_info)))
325 (*(p->show_device_property_info))(seq, p->devdata);
331 static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
332 size_t count, loff_t *ppos)
334 struct seq_file *seq = (struct seq_file *)file->private_data;
335 struct easyproc_driver_info *p = NULL;
339 p = (struct easyproc_driver_info *)(seq->private);
340 if ((!p) || (!(p->Write_driver_info)))
342 if (count >= sizeof(local_buf))
344 if (copy_from_user(local_buf, buffer, count))
346 local_buf[count] = '\0'; /* be friendly */
347 (*(p->Write_driver_info))(local_buf, count, ppos);
353 static ssize_t proc_write_device(struct file *file, const char __user *buffer,
354 size_t count, loff_t *ppos)
356 struct seq_file *seq = (struct seq_file *)file->private_data;
357 struct easyproc_device_info *p = NULL;
361 p = (struct easyproc_device_info *)(seq->private);
362 if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
364 if (count >= sizeof(local_buf))
366 if (copy_from_user(local_buf, buffer, count))
368 local_buf[count] = '\0'; /* be friendly */
369 (*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);