2 * Linux CAN-bus device driver.
3 * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4 * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
5 * email:pisa@cmp.felk.cvut.cz
6 * This software is released under the GPL-License.
7 * Version lincan-0.3 17 Jun 2004
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/proc.h"
14 #include "../include/setup.h"
16 #define __NO_VERSION__
17 #include <linux/module.h>
19 int add_channel_to_procdir(struct candevice_t *candev);
20 int remove_channel_from_procdir(void);
21 int add_object_to_procdir(int chip_nr);
22 int remove_object_from_procdir(int chip_nr);
24 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
25 static int can_proc_readlink(struct proc_dir_entry *ent, char *page);
28 static int cc=0; /* static counter for each CAN chip */
30 static struct canproc_t can_proc_base;
31 static struct canproc_t *base=&can_proc_base;
33 /* The following functions are needed only for kernel version 2.2. Kernel
34 * version 2.4 already defines them for us.
36 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
37 static void can_fill_inode(struct inode *inode, int fill)
45 static struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
46 struct proc_dir_entry *parent)
48 struct proc_dir_entry *new_entry = NULL;
58 new_entry = (struct proc_dir_entry *)
59 can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
61 if (new_entry == NULL)
64 memset(new_entry, 0, sizeof(struct proc_dir_entry));
66 /* Store copy of the proc entry name */
67 namestore = ((char *) new_entry) + sizeof(struct proc_dir_entry);
68 memcpy(namestore, name, namelen + 1);
70 new_entry->low_ino = 0;
71 new_entry->namelen = namelen;
72 new_entry->name = namestore;
73 new_entry->mode = mode;
75 new_entry->fill_inode = can_fill_inode;
76 new_entry->parent = parent;
78 proc_register(parent, new_entry);
83 static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
86 proc_unregister(parent, del->low_ino);
87 can_checked_free(del);
94 static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
96 char *link_dest = (char*)ent->data;
98 strcpy(page, link_dest);
99 return strlen(link_dest);
104 /* This compatibility version of proc_symlink does not store local copy of destination */
105 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
106 struct proc_dir_entry *parent, const char *dest)
108 struct proc_dir_entry *entry;
111 entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
114 entry->readlink_proc = can_proc_readlink;
119 #else /* Functions forwarded for kernel 2.4 and above */
121 static inline struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
122 struct proc_dir_entry *parent)
124 return create_proc_entry(name, mode, parent);
128 /* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */
129 /* The newer kernels use entry name instead of pointer to the entry */
130 static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
132 if(!del) return -ENODEV;
133 remove_proc_entry(del->name,parent);
137 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
138 struct proc_dir_entry *parent, const char *dest)
140 return proc_symlink(name, parent, dest);
143 #endif /* Functions required for kernel 2.2 */
145 /* can_init_procdir registers the entire CAN directory tree recursively at
148 int can_init_procdir(void)
151 struct candevice_t *candev;
152 base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
153 S_IXUGO, &proc_root);
154 if (base->can_proc_entry == NULL)
157 for (board=0; board<hardware_p->nr_boards; board++) {
158 candev=hardware_p->candevice[board];
159 if(candev) add_channel_to_procdir(candev);
165 /* can_delete_procdir removes the entire CAN tree from the proc system */
166 int can_delete_procdir(void)
168 if (remove_channel_from_procdir())
171 if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
177 int add_channel_to_procdir(struct candevice_t *candev)
181 for (i=0; i < candev->nr_all_chips; i++) {
183 base->channel[cc] = (struct channelproc_t *)
184 can_checked_malloc(sizeof(struct channelproc_t));
185 if (base->channel[cc] == NULL)
188 sprintf(base->channel[cc]->ch_name, "channel%d",cc);
190 base->channel[cc]->ch_entry = can_create_proc_entry(
191 base->channel[cc]->ch_name,
192 S_IFDIR | S_IRUGO |S_IXUGO,
193 base->can_proc_entry);
195 if (base->channel[cc]->ch_entry == NULL)
198 add_object_to_procdir(cc);
206 int remove_channel_from_procdir(void)
212 if(!base->channel[cc]) continue;
214 if (remove_object_from_procdir(cc))
217 /* name: base->channel[cc]->ch_name */
218 if (can_remove_proc_entry(base->channel[cc]->ch_entry,
219 base->can_proc_entry))
222 can_checked_free(base->channel[cc]);
223 base->channel[cc] = NULL;
230 int add_object_to_procdir(int chip_nr)
234 max_objects=chips_p[chip_nr]->max_objects;
236 for (i=0; i<max_objects; i++) {
237 base->channel[chip_nr]->object[i] = (struct objectproc_t *)
238 can_checked_malloc(sizeof(struct objectproc_t));
240 if (base->channel[chip_nr]->object[i] == NULL)
243 sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
244 sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
246 base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry(
247 base->channel[chip_nr]->object[i]->obj_name,
248 S_IFDIR | S_IRUGO | S_IXUGO,
249 base->channel[chip_nr]->ch_entry);
250 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
253 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
254 chips_p[chip_nr]->msgobj[i]->minor);
256 base->channel[chip_nr]->object[i]->lnk = can_proc_symlink(
257 base->channel[chip_nr]->object[i]->lnk_name,
258 base->channel[chip_nr]->object[i]->obj_entry,
259 base->channel[chip_nr]->object[i]->lnk_dev);
260 if (base->channel[chip_nr]->object[i]->lnk == NULL)
267 int remove_object_from_procdir(int chip_nr)
271 obj=chips_p[chip_nr]->max_objects;
273 for (i=0; i<obj; i++) {
274 if(!base->channel[chip_nr]->object[i]) continue;
276 /* name: base->channel[chip_nr]->object[i]->lnk_name */
277 if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk,
278 base->channel[chip_nr]->object[i]->obj_entry))
280 /* name: base->channel[chip_nr]->object[i]->obj_name */
281 if (can_remove_proc_entry(
282 base->channel[chip_nr]->object[i]->obj_entry,
283 base->channel[chip_nr]->ch_entry))
286 can_checked_free(base->channel[chip_nr]->object[i]);
288 base->channel[chip_nr]->object[i]=NULL;