1 /**************************************************************************/
2 /* File: proc.c - proc filesystem entries for CAN driver */
4 /* LinCAN - (Not only) Linux CAN bus driver */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
7 /* Funded by OCERA and FRESCOR IST projects */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
10 /* LinCAN is free software; you can redistribute it and/or modify it */
11 /* under terms of the GNU General Public License as published by the */
12 /* Free Software Foundation; either version 2, or (at your option) any */
13 /* later version. LinCAN is distributed in the hope that it will be */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16 /* General Public License for more details. You should have received a */
17 /* copy of the GNU General Public License along with LinCAN; see file */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
19 /* Cambridge, MA 02139, USA. */
21 /* To allow use of LinCAN in the compact embedded systems firmware */
22 /* and RT-executives (RTEMS for example), main authors agree with next */
23 /* special exception: */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce */
27 /* an application image/executable, does not by itself cause the */
28 /* resulting application image/executable to be covered by */
29 /* the GNU General Public License. */
30 /* This exception does not however invalidate any other reasons */
31 /* why the executable file might be covered by the GNU Public License. */
32 /* Publication of enhanced or derived LinCAN files is required although. */
33 /**************************************************************************/
35 #include "../include/can.h"
36 #include "../include/can_sysdep.h"
37 #include "../include/main.h"
38 #include "../include/proc.h"
39 #include "../include/setup.h"
41 #define __NO_VERSION__
42 #include <linux/module.h>
43 #include <linux/mutex.h>
45 int add_channel_to_procdir(struct candevice_t *candev);
46 int remove_channels_from_procdir(void);
47 int remove_channel_from_procdir(struct candevice_t *candev);
48 int add_object_to_procdir(int chip_nr);
49 int remove_object_from_procdir(int chip_nr);
51 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
52 static int can_proc_readlink(struct proc_dir_entry *ent, char *page);
55 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
56 #define CAN_PROC_ROOT (&proc_root)
58 #define CAN_PROC_ROOT (NULL)
59 #endif /* >= 2.6.26 */
61 static int cc=0; /* static counter for each CAN chip */
63 static struct canproc_t can_proc_base;
64 static struct canproc_t *base=&can_proc_base;
65 DEFINE_MUTEX(proc_mutex); /* synchronize access to canproc_t array */
67 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
69 #include <linux/seq_file.h>
71 #define CAN_PROC_SHOW_SINGLE_OPS_DECLARE(ops_name, show_function) \
72 static int ops_name##_open(struct inode *inode, struct file *file) \
74 return single_open(file, show_function, PDE_DATA(inode)); \
76 static const struct file_operations ops_name = { \
77 .owner = THIS_MODULE, \
78 .open = ops_name##_open, \
80 .llseek = seq_lseek, \
81 .release = single_release, \
84 typedef struct file_operations can_proc_read_entry_ops_t;
85 typedef struct seq_file can_proc_seq_file_t;
87 static inline void *can_seq_data(can_proc_seq_file_t *sqf)
92 #define can_seq_printf seq_printf
94 struct proc_dir_entry *can_create_proc_read_entry(const char *name,
95 mode_t mode, struct proc_dir_entry *parent,
96 const can_proc_read_entry_ops_t *proc_read_entry_ops, void * data)
98 return proc_create_data(name, mode, parent, proc_read_entry_ops, data);
101 struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode,
102 struct proc_dir_entry *parent)
104 return proc_mkdir_mode(name, mode, parent);
107 static int can_proc_remove(struct proc_dir_entry *del)
109 if(!del) return -ENODEV;
114 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
115 struct proc_dir_entry *parent, const char *dest)
117 return proc_symlink(name, parent, dest);
120 #else /* kernel older than 3.10 */
122 typedef read_proc_t *can_proc_read_entry_ops_t;
128 } can_proc_seq_file_t;
130 #define CAN_PROC_SHOW_SINGLE_OPS_DECLARE(ops_name, show_function) \
131 static int ops_name##_show_wrapper(char *buf, char **start, off_t offset, \
132 int count, int *eof, void *data) \
134 can_proc_seq_file_t seq_pos = { .len = 0, .buf = buf, .limit = PAGE_SIZE, \
137 show_function(&seq_pos, data); \
138 return seq_pos.len; \
140 const static can_proc_read_entry_ops_t ops_name = ops_name##_show_wrapper;
142 static inline void *can_seq_data(can_proc_seq_file_t *sqf)
147 static inline int can_seq_printf(can_proc_seq_file_t *sqf, const char *f, ...)
152 ret = vsnprintf(sqf->buf + sqf->len, sqf->limit - sqf->len, f, args);
154 if (sqf->len > sqf->limit)
155 sqf->len = sqf->limit;
160 struct proc_dir_entry *can_create_proc_read_entry(const char *name,
161 mode_t mode, struct proc_dir_entry *parent,
162 const can_proc_read_entry_ops_t *proc_read_entry_ops, void * data)
164 return create_proc_read_entry(name, mode, parent, *proc_read_entry_ops, data);
167 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0))
169 struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode,
170 struct proc_dir_entry *parent)
172 return create_proc_entry(name, S_IFDIR | mode, parent);
175 /* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */
176 /* The newer kernels use entry name instead of pointer to the entry */
177 static int can_proc_remove(struct proc_dir_entry *del)
179 if(!del) return -ENODEV;
180 remove_proc_entry(del->name, del->parent);
184 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
185 struct proc_dir_entry *parent, const char *dest)
187 return proc_symlink(name, parent, dest);
190 #else /* ancient Linux kernel older than 2.3.0 */
191 static void can_fill_inode(struct inode *inode, int fill)
199 static struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
200 struct proc_dir_entry *parent)
202 struct proc_dir_entry *new_entry = NULL;
208 namelen=strlen(name);
212 new_entry = (struct proc_dir_entry *)
213 can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
215 if (new_entry == NULL)
218 memset(new_entry, 0, sizeof(struct proc_dir_entry));
220 /* Store copy of the proc entry name */
221 namestore = ((char *) new_entry) + sizeof(struct proc_dir_entry);
222 memcpy(namestore, name, namelen + 1);
224 new_entry->low_ino = 0;
225 new_entry->namelen = namelen;
226 new_entry->name = namestore;
227 new_entry->mode = mode;
228 new_entry->nlink = 0;
229 new_entry->fill_inode = can_fill_inode;
230 new_entry->parent = parent;
232 proc_register(parent, new_entry);
237 struct proc_dir_entry *can_create_proc_read_entry(const char *name,
238 mode_t mode, struct proc_dir_entry *parent,
239 read_proc_t *read_proc, void * data)
241 return create_proc_read_entry(name, mode, parent, read_proc, data);
244 struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode,
245 struct proc_dir_entry *parent)
247 return can_create_proc_entry(name, S_IFDIR | mode, parent);
250 static int can_proc_remove(struct proc_dir_entry *del)
253 proc_unregister(del->parent, del->low_ino);
254 can_checked_free(del);
261 static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
263 char *link_dest = (char*)ent->data;
265 strcpy(page, link_dest);
266 return strlen(link_dest);
271 /* This compatibility version of proc_symlink does not store local copy of destination */
272 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
273 struct proc_dir_entry *parent, const char *dest)
275 struct proc_dir_entry *entry;
278 entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
281 entry->readlink_proc = can_proc_readlink;
286 #endif /* Linux 2.2 - 2.3 kernels */
288 #endif /* Linux kernel 3.6 and 3.10+ */
290 /* can_init_procdir registers the entire CAN directory tree recursively at
293 int can_init_procdir(void)
296 struct candevice_t *candev;
298 mutex_init(&proc_mutex);
300 base->can_proc_entry = can_proc_mkdir_mode("can", S_IFDIR | S_IRUGO |
301 S_IXUGO, CAN_PROC_ROOT);
302 if (base->can_proc_entry == NULL)
305 for (board=0; board<hardware_p->nr_boards; board++) {
306 candev=hardware_p->candevice[board];
307 if(candev) add_channel_to_procdir(candev);
313 /* can_init_procentry registers entry of a new board in CAN directory tree at
316 int can_init_procentry(int board)
318 struct candevice_t *candev;
319 candev=hardware_p->candevice[board];
321 return add_channel_to_procdir(candev);
325 /* can_delete_procdir removes the entire CAN tree from the proc system */
326 int can_delete_procdir(void)
328 if (remove_channels_from_procdir())
331 if (can_proc_remove(base->can_proc_entry))
337 /* can_delete_procentry removes device entries from CAN tree in the proc system */
338 int can_delete_procentry(struct candevice_t *candev)
340 if (remove_channel_from_procdir(candev))
346 static int can_chip_procinfo_show(can_proc_seq_file_t *sqf, void *data)
348 struct canchip_t *chip=can_seq_data(sqf);
350 /* Generic chip info */
351 can_seq_printf(sqf, "type : %s\n",chip->chip_type);
352 can_seq_printf(sqf, "index : %d\n",chip->chip_idx);
353 can_seq_printf(sqf, "irq : %d\n",chip->chip_irq);
354 can_seq_printf(sqf, "addr : %lu\n",
355 can_ioptr2ulong(chip->chip_base_addr));
356 can_seq_printf(sqf, "config : %s\n",
357 (chip->flags & CHIP_CONFIGURED) ? "yes":"no");
358 can_seq_printf(sqf, "clock : %ld Hz\n",chip->clock);
359 can_seq_printf(sqf, "baud : %ld\n",chip->baudrate);
360 can_seq_printf(sqf, "num obj : %d\n",chip->max_objects);
363 /* Chip specific info if available */
364 if(chip->chipspecops->get_info)
365 len += (chip->chipspecops->get_info)(chip,buf+len);
371 CAN_PROC_SHOW_SINGLE_OPS_DECLARE(can_chip_procinfo_ops, can_chip_procinfo_show);
373 int add_channel_to_procdir(struct candevice_t *candev)
377 mutex_lock(&proc_mutex);
378 for (i=0; i < MAX_TOT_CHIPS; i++){
379 if (!chips_p[i]) continue;
380 if (chips_p[i]->hostdevice != candev) continue;
382 base->channel[i] = (struct channelproc_t *)
383 can_checked_malloc(sizeof(struct channelproc_t));
384 if (base->channel[i] == NULL){
385 mutex_unlock(&proc_mutex);
389 sprintf(base->channel[i]->ch_name, "channel%d",i);
391 base->channel[i]->ch_entry = can_proc_mkdir_mode(
392 base->channel[i]->ch_name,
393 S_IFDIR | S_IRUGO |S_IXUGO,
394 base->can_proc_entry);
396 if (base->channel[i]->ch_entry == NULL){
397 mutex_unlock(&proc_mutex);
401 add_object_to_procdir(i);
403 can_create_proc_read_entry("chip_info", /* proc entry name */
404 0, /* protection mask, 0->default */
405 base->channel[i]->ch_entry, /* parent dir, NULL->/proc */
406 &can_chip_procinfo_ops,
410 mutex_unlock(&proc_mutex);
415 int remove_channels_from_procdir(void)
419 mutex_lock(&proc_mutex);
420 for (i=0; i < MAX_TOT_CHIPS; i++){
421 if (!chips_p[i]) continue;
425 if(!base->channel[i]) continue;
427 remove_proc_entry("chip_info", base->channel[i]->ch_entry);
429 if (remove_object_from_procdir(i)){
430 mutex_unlock(&proc_mutex);
434 /* name: base->channel[cc]->ch_name */
435 if (can_proc_remove(base->channel[i]->ch_entry)){
436 mutex_unlock(&proc_mutex);
440 can_checked_free(base->channel[i]);
441 base->channel[i] = NULL;
443 mutex_unlock(&proc_mutex);
448 int remove_channel_from_procdir(struct candevice_t *candev)
452 mutex_lock(&proc_mutex);
453 for (i=0; i < MAX_TOT_CHIPS; i++){
454 if (!chips_p[i]) continue;
455 if (chips_p[i]->hostdevice != candev) continue;
456 if (!base->channel[i]) continue;
458 remove_proc_entry("chip_info", base->channel[i]->ch_entry);
460 if (remove_object_from_procdir(i)){
461 mutex_unlock(&proc_mutex);
465 /* name: base->channel[cc]->ch_name */
466 if (can_proc_remove(base->channel[i]->ch_entry)){
467 mutex_unlock(&proc_mutex);
471 can_checked_free(base->channel[i]);
472 base->channel[i] = NULL;
476 mutex_unlock(&proc_mutex);
482 int add_object_to_procdir(int chip_nr)
486 max_objects=chips_p[chip_nr]->max_objects;
488 for (i=0; i<max_objects; i++) {
489 base->channel[chip_nr]->object[i] = (struct objectproc_t *)
490 can_checked_malloc(sizeof(struct objectproc_t));
492 if (base->channel[chip_nr]->object[i] == NULL)
495 sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
496 sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
498 base->channel[chip_nr]->object[i]->obj_entry = can_proc_mkdir_mode(
499 base->channel[chip_nr]->object[i]->obj_name,
500 S_IFDIR | S_IRUGO | S_IXUGO,
501 base->channel[chip_nr]->ch_entry);
502 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
505 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
506 chips_p[chip_nr]->msgobj[i]->minor);
508 base->channel[chip_nr]->object[i]->lnk = can_proc_symlink(
509 base->channel[chip_nr]->object[i]->lnk_name,
510 base->channel[chip_nr]->object[i]->obj_entry,
511 base->channel[chip_nr]->object[i]->lnk_dev);
512 if (base->channel[chip_nr]->object[i]->lnk == NULL)
519 int remove_object_from_procdir(int chip_nr)
523 obj=chips_p[chip_nr]->max_objects;
525 for (i=0; i<obj; i++) {
526 if(!base->channel[chip_nr]->object[i]) continue;
528 /* name: base->channel[chip_nr]->object[i]->lnk_name */
529 if (can_proc_remove( base->channel[chip_nr]->object[i]->lnk))
531 /* name: base->channel[chip_nr]->object[i]->obj_name */
532 if (can_proc_remove(base->channel[chip_nr]->object[i]->obj_entry))
535 can_checked_free(base->channel[chip_nr]->object[i]);
537 base->channel[chip_nr]->object[i]=NULL;