]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/unisys/visorutil/easyproc.c
staging: unisys: fix NULL pointer comparisons in uislib.c
[karo-tx-linux.git] / drivers / staging / unisys / visorutil / easyproc.c
1 /* Copyright (C) 2010 - 2013 UNISYS CORPORATION
2  * All rights reserved.
3  *
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.
8  *
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
13  * details.
14  */
15
16 /** @file *********************************************************************
17  *
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().
24  *
25  *      void show_device_info(struct seq_file *seq, void *p);
26  *      void show_driver_info(struct seq_file *seq);
27  *
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().
31  *
32  ******************************************************************************
33  */
34
35 #include <linux/proc_fs.h>
36
37 #include "timskmod.h"
38 #include "easyproc.h"
39
40 #define MYDRVNAME "easyproc"
41
42
43
44 /*
45  *   /proc/<ProcId>                              ProcDir
46  *   /proc/<ProcId>/driver                       ProcDriverDir
47  *   /proc/<ProcId>/driver/diag                  ProcDriverDiagFile
48  *   /proc/<ProcId>/device                       ProcDeviceDir
49  *   /proc/<ProcId>/device/0                     procDevicexDir
50  *   /proc/<ProcId>/device/0/diag                procDevicexDiagFile
51  */
52
53
54 static ssize_t proc_write_device(struct file *file, const char __user *buffer,
55                                  size_t count, loff_t *ppos);
56 static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
57                                  size_t count, loff_t *ppos);
58
59 static struct proc_dir_entry *
60         createProcDir(char *name, struct proc_dir_entry *parent)
61 {
62         struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
63         return p;
64 }
65
66 static int seq_show_driver(struct seq_file *seq, void *offset);
67 static int proc_open_driver(struct inode *inode, struct file *file)
68 {
69         return single_open(file, seq_show_driver, PDE_DATA(inode));
70 }
71 static const struct file_operations proc_fops_driver = {
72         .open = proc_open_driver,
73         .read = seq_read,
74         .write = proc_write_driver,
75         .llseek = seq_lseek,
76         .release = single_release,
77 };
78
79 static int seq_show_device(struct seq_file *seq, void *offset);
80 static int seq_show_device_property(struct seq_file *seq, void *offset);
81 static int proc_open_device(struct inode *inode, struct file *file)
82 {
83         return single_open(file, seq_show_device, PDE_DATA(inode));
84 }
85 static const struct file_operations proc_fops_device = {
86         .open = proc_open_device,
87         .read = seq_read,
88         .write = proc_write_device,
89         .llseek = seq_lseek,
90         .release = single_release,
91 };
92 static int proc_open_device_property(struct inode *inode, struct file *file)
93 {
94         return single_open(file, seq_show_device_property, PDE_DATA(inode));
95 }
96 static const struct file_operations proc_fops_device_property = {
97         .open = proc_open_device_property,
98         .read = seq_read,
99         .llseek = seq_lseek,
100         .release = single_release,
101 };
102
103
104
105 void visor_easyproc_InitDriver(struct easyproc_driver_info *pdriver,
106                                char *procId,
107                                void (*show_driver_info)(struct seq_file *),
108                                void (*show_device_info)(struct seq_file *,
109                                                         void *))
110 {
111         memset(pdriver, 0, sizeof(struct easyproc_driver_info));
112         pdriver->ProcId = procId;
113         pdriver->Show_driver_info = show_driver_info;
114         pdriver->Show_device_info = show_device_info;
115         if (pdriver->ProcDir == NULL)
116                 pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
117         if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
118                 pdriver->ProcDriverDir = createProcDir("driver",
119                                                        pdriver->ProcDir);
120         if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
121                 pdriver->ProcDeviceDir = createProcDir("device",
122                                                        pdriver->ProcDir);
123         if ((pdriver->ProcDriverDir != NULL) &&
124             (pdriver->ProcDriverDiagFile == NULL)) {
125                 pdriver->ProcDriverDiagFile =
126                         proc_create_data("diag", 0,
127                                          pdriver->ProcDriverDir,
128                                          &proc_fops_driver, pdriver);
129         }
130 }
131 EXPORT_SYMBOL_GPL(visor_easyproc_InitDriver);
132
133
134
135 void visor_easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
136                                  char *procId,
137                                  void (*show_driver_info)(struct seq_file *),
138                                  void (*show_device_info)(struct seq_file *,
139                                                           void *),
140                                  void (*write_driver_info)(char *buf,
141                                                            size_t count,
142                                                            loff_t *ppos),
143                                  void (*write_device_info)(char *buf,
144                                                            size_t count,
145                                                            loff_t *ppos,
146                                                            void *p))
147 {
148         visor_easyproc_InitDriver(pdriver, procId,
149                                   show_driver_info, show_device_info);
150         pdriver->Write_driver_info = write_driver_info;
151         pdriver->Write_device_info = write_device_info;
152 }
153 EXPORT_SYMBOL_GPL(visor_easyproc_InitDriverEx);
154
155
156
157 void visor_easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
158 {
159         if (pdriver->ProcDriverDiagFile != NULL) {
160                 remove_proc_entry("diag", pdriver->ProcDriverDir);
161                 pdriver->ProcDriverDiagFile = NULL;
162         }
163         if (pdriver->ProcDriverDir != NULL) {
164                 remove_proc_entry("driver", pdriver->ProcDir);
165                 pdriver->ProcDriverDir = NULL;
166         }
167         if (pdriver->ProcDeviceDir != NULL) {
168                 remove_proc_entry("device", pdriver->ProcDir);
169                 pdriver->ProcDeviceDir = NULL;
170         }
171         if (pdriver->ProcDir != NULL) {
172                 remove_proc_entry(pdriver->ProcId, NULL);
173                 pdriver->ProcDir = NULL;
174         }
175         pdriver->ProcId = NULL;
176         pdriver->Show_driver_info = NULL;
177         pdriver->Show_device_info = NULL;
178         pdriver->Write_driver_info = NULL;
179         pdriver->Write_device_info = NULL;
180 }
181 EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDriver);
182
183
184
185 void visor_easyproc_InitDevice(struct easyproc_driver_info *pdriver,
186                                struct easyproc_device_info *p, int devno,
187                                void *devdata)
188 {
189         if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
190                 char s[29];
191
192                 sprintf(s, "%d", devno);
193                 p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
194                 p->devno = devno;
195         }
196         p->devdata = devdata;
197         p->pdriver = pdriver;
198         p->devno = devno;
199         if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
200                 p->procDevicexDiagFile =
201                         proc_create_data("diag", 0, p->procDevicexDir,
202                                          &proc_fops_device, p);
203         }
204         memset(&(p->device_property_info[0]), 0,
205                sizeof(p->device_property_info));
206 }
207 EXPORT_SYMBOL_GPL(visor_easyproc_InitDevice);
208
209
210
211 void visor_easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
212                                          void (*show_property_info)
213                                          (struct seq_file *, void *),
214                                          char *property_name)
215 {
216         size_t i;
217         struct easyproc_device_property_info *px = NULL;
218
219         if (p->procDevicexDir == NULL)
220                 return;
221         for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
222                 if (p->device_property_info[i].procEntry == NULL) {
223                         px = &(p->device_property_info[i]);
224                         break;
225                 }
226         }
227         if (!px)
228                 return;
229
230         px->devdata = p->devdata;
231         px->pdriver = p->pdriver;
232         px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
233                                          &proc_fops_device_property, px);
234         if (strlen(property_name)+1 > sizeof(px->property_name)) {
235                 return;
236         }
237         strcpy(px->property_name, property_name);
238         if (px->procEntry == NULL) {
239                 return;
240         }
241         px->show_device_property_info = show_property_info;
242 }
243 EXPORT_SYMBOL_GPL(visor_easyproc_CreateDeviceProperty);
244
245
246
247 void visor_easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
248                                  struct easyproc_device_info *p, int devno)
249 {
250         size_t i;
251
252         for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
253                 if (p->device_property_info[i].procEntry != NULL) {
254                         struct easyproc_device_property_info *px =
255                                 &(p->device_property_info[i]);
256                         remove_proc_entry(px->property_name, p->procDevicexDir);
257                         px->procEntry = NULL;
258                 }
259         }
260         if (p->procDevicexDiagFile != NULL) {
261                 remove_proc_entry("diag", p->procDevicexDir);
262                 p->procDevicexDiagFile = NULL;
263         }
264         if (p->procDevicexDir != NULL) {
265                 char s[29];
266
267                 sprintf(s, "%d", devno);
268                 remove_proc_entry(s, pdriver->ProcDeviceDir);
269                 p->procDevicexDir = NULL;
270         }
271         p->devdata = NULL;
272         p->pdriver = NULL;
273 }
274 EXPORT_SYMBOL_GPL(visor_easyproc_DeInitDevice);
275
276
277
278 static int seq_show_driver(struct seq_file *seq, void *offset)
279 {
280         struct easyproc_driver_info *p =
281                 (struct easyproc_driver_info *)(seq->private);
282         if (!p)
283                 return 0;
284         (*(p->Show_driver_info))(seq);
285         return 0;
286 }
287
288
289
290 static int seq_show_device(struct seq_file *seq, void *offset)
291 {
292         struct easyproc_device_info *p =
293                 (struct easyproc_device_info *)(seq->private);
294         if ((!p) || (!(p->pdriver)))
295                 return 0;
296         (*(p->pdriver->Show_device_info))(seq, p->devdata);
297         return 0;
298 }
299
300
301
302 static int seq_show_device_property(struct seq_file *seq, void *offset)
303 {
304         struct easyproc_device_property_info *p =
305                 (struct easyproc_device_property_info *)(seq->private);
306         if ((!p) || (!(p->show_device_property_info)))
307                 return 0;
308         (*(p->show_device_property_info))(seq, p->devdata);
309         return 0;
310 }
311
312
313
314 static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
315                                  size_t count, loff_t *ppos)
316 {
317         struct seq_file *seq = (struct seq_file *)file->private_data;
318         struct easyproc_driver_info *p = NULL;
319         char local_buf[256];
320
321         if (seq == NULL)
322                 return 0;
323         p = (struct easyproc_driver_info *)(seq->private);
324         if ((!p) || (!(p->Write_driver_info)))
325                 return 0;
326         if (count >= sizeof(local_buf))
327                 return -ENOMEM;
328         if (copy_from_user(local_buf, buffer, count))
329                 return -EFAULT;
330         local_buf[count] = '\0';  /* be friendly */
331         (*(p->Write_driver_info))(local_buf, count, ppos);
332         return count;
333 }
334
335
336
337 static ssize_t proc_write_device(struct file *file, const char __user *buffer,
338                                  size_t count, loff_t *ppos)
339 {
340         struct seq_file *seq = (struct seq_file *)file->private_data;
341         struct easyproc_device_info *p = NULL;
342         char local_buf[256];
343
344         if (seq == NULL)
345                 return 0;
346         p = (struct easyproc_device_info *)(seq->private);
347         if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
348                 return 0;
349         if (count >= sizeof(local_buf))
350                 return -ENOMEM;
351         if (copy_from_user(local_buf, buffer, count))
352                 return -EFAULT;
353         local_buf[count] = '\0';  /* be friendly */
354         (*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);
355         return count;
356 }