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.2 9 Jul 2003
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(void);
24 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
25 static int candev_readlink(struct proc_dir_entry *de, char *page);
28 static int cc=0; /* static counter for each CAN chip */
30 struct canproc_t can_proc_base;
31 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 * new_can_proc_entry(unsigned short inode,
46 const char *name, mode_t mode, nlink_t nlink, struct proc_dir_entry *parent)
48 struct proc_dir_entry *new_entry = NULL;
50 new_entry = (struct proc_dir_entry *)
51 can_checked_malloc(sizeof(struct proc_dir_entry));
52 if (new_entry == NULL)
55 memset(new_entry, 0, sizeof(struct proc_dir_entry));
57 new_entry->low_ino = inode;
58 new_entry->namelen = strlen(name);
59 new_entry->name = name;
60 new_entry->mode = mode;
61 new_entry->nlink = nlink;
62 new_entry->fill_inode = can_fill_inode;
63 new_entry->parent = parent;
65 proc_register(parent, new_entry);
70 int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
73 proc_unregister(parent, del->low_ino);
74 can_checked_free(del);
79 #endif // Functions required for kernel 2.2
81 /* can_init_procdir registers the entire CAN directory tree recursively at
84 int can_init_procdir(void)
87 struct candevice_t *candev;
88 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
89 base->can_proc_entry = new_can_proc_entry(0, "can", S_IFDIR | S_IRUGO |
90 S_IXUGO, 0, &proc_root);
92 base->can_proc_entry = create_proc_entry("can", S_IFDIR | S_IRUGO |
95 if (base->can_proc_entry == NULL)
98 for (board=0; board<hardware_p->nr_boards; board++) {
99 candev=hardware_p->candevice[board];
100 if(candev) add_channel_to_procdir(candev);
106 /* can_delete_procdir removes the entire CAN tree from the proc system */
107 int can_delete_procdir(void)
109 if (remove_channel_from_procdir())
111 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
112 if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
115 remove_proc_entry("can", &proc_root);
121 int add_channel_to_procdir(struct candevice_t *candev)
125 for (i=0; i < candev->nr_all_chips; i++) {
127 base->channel[cc] = (struct channelproc_t *)
128 can_checked_malloc(sizeof(struct channelproc_t));
129 if (base->channel[cc] == NULL)
132 sprintf(base->channel[cc]->ch_name, "channel%d",cc);
134 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
135 base->channel[cc]->ch_entry = new_can_proc_entry(0,
136 base->channel[cc]->ch_name,
137 S_IFDIR | S_IRUGO | S_IXUGO, 0,
138 base->can_proc_entry);
140 base->channel[cc]->ch_entry = create_proc_entry(
141 base->channel[cc]->ch_name,
142 S_IFDIR | S_IRUGO |S_IXUGO,
143 base->can_proc_entry);
145 if (base->channel[cc]->ch_entry == NULL)
148 add_object_to_procdir(cc);
156 int remove_channel_from_procdir(void)
161 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
162 if (can_remove_proc_entry(base->channel[cc]->ch_entry,
163 base->can_proc_entry))
166 remove_proc_entry(base->channel[cc]->ch_name,
167 base->can_proc_entry);
169 if (remove_object_from_procdir())
177 int add_object_to_procdir(int chip_nr)
181 max_objects=chips_p[chip_nr]->max_objects;
183 for (i=0; i<max_objects; i++) {
184 base->channel[chip_nr]->object[i] = (struct objectproc_t *)
185 can_checked_malloc(sizeof(struct objectproc_t));
187 if (base->channel[chip_nr]->object[i] == NULL)
190 sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
191 sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
193 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
194 base->channel[chip_nr]->object[i]->obj_entry=new_can_proc_entry(
195 0, base->channel[chip_nr]->object[i]->obj_name,
196 S_IFDIR | S_IRUGO | S_IXUGO, 0,
197 base->channel[chip_nr]->ch_entry);
198 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
200 base->channel[chip_nr]->object[i]->lnk = new_can_proc_entry(
201 0, base->channel[chip_nr]->object[i]->lnk_name,
202 S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO,
203 0, base->channel[chip_nr]->object[i]->obj_entry);
204 if (base->channel[chip_nr]->object[i]->lnk == NULL)
206 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can");
207 base->channel[chip_nr]->object[i]->lnk->readlink_proc =
211 base->channel[chip_nr]->object[i]->obj_entry = create_proc_entry(
212 base->channel[chip_nr]->object[i]->obj_name,
213 S_IFDIR | S_IRUGO | S_IXUGO,
214 base->channel[chip_nr]->ch_entry);
215 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
217 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
218 chips_p[chip_nr]->msgobj[i]->minor);
219 base->channel[chip_nr]->object[i]->lnk = proc_symlink(
220 base->channel[chip_nr]->object[i]->lnk_name,
221 base->channel[chip_nr]->object[i]->obj_entry,
222 base->channel[chip_nr]->object[i]->lnk_dev);
223 if (base->channel[chip_nr]->object[i]->lnk == NULL)
231 int remove_object_from_procdir(void)
235 obj=chips_p[cc]->max_objects;
237 for (i=0; i<obj; i++) {
238 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
239 if (can_remove_proc_entry( base->channel[cc]->object[i]->lnk,
240 base->channel[cc]->object[i]->obj_entry))
242 if (can_remove_proc_entry(
243 base->channel[cc]->object[i]->obj_entry,
244 base->channel[cc]->ch_entry))
247 remove_proc_entry(base->channel[cc]->object[i]->lnk_name,
248 base->channel[cc]->object[i]->obj_entry);
249 remove_proc_entry(base->channel[cc]->object[i]->obj_name,
250 base->channel[cc]->ch_entry);
257 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
258 static int candev_readlink(struct proc_dir_entry *de, char *page)
260 int i=0, nchip=0, nobj=0;
261 char chip[20], object[20], tmp[6];
263 sprintf(chip, de->parent->parent->name+7);
264 sprintf(object, de->parent->name+6);
266 for (i=0; i<MAX_TOT_CHIPS; i++) {
268 if (!strcmp(chip,tmp)) {
273 for (i=0; i<MAX_MSGOBJS; i++) {
275 if (!strcmp(object,tmp)) {
281 return sprintf(page,"/dev/can%d",chips_p[nchip]->msgobj[nobj]->minor );
283 #endif //End of candev_readlink for kernel 2.2