]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/proc.c
254aabcac3feb7944d39439dc17d6a15a662b401
[lincan.git] / lincan / src / proc.c
1 /* proc.c
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
8  */ 
9
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"
15
16 #define __NO_VERSION__
17 #include <linux/module.h>
18
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);
23
24 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
25 static int candev_readlink(struct proc_dir_entry *de, char *page);
26 #endif
27
28 static int cc=0; /* static counter for each CAN chip */
29
30 struct canproc_t can_proc_base;
31 struct canproc_t *base=&can_proc_base;
32
33 /* The following functions are needed only for kernel version 2.2. Kernel
34  * version 2.4 already defines them for us.
35  */
36 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
37 static void can_fill_inode(struct inode *inode, int fill)
38 {
39         if (fill)
40                 MOD_INC_USE_COUNT;
41         else
42                 MOD_DEC_USE_COUNT;
43 }
44
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)
47 {
48         struct proc_dir_entry *new_entry = NULL;
49
50         new_entry = (struct proc_dir_entry *) 
51                         can_checked_malloc(sizeof(struct proc_dir_entry));
52         if (new_entry == NULL)
53                 return NULL;
54
55         memset(new_entry, 0, sizeof(struct proc_dir_entry));
56
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;
64
65         proc_register(parent, new_entry);
66
67         return new_entry;
68 }
69
70 int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
71 {
72         if (del != NULL) {
73                 proc_unregister(parent, del->low_ino);
74                 can_checked_free(del);
75                 return 0;
76         }
77         else return -ENODEV;
78 }
79 #endif // Functions required for kernel 2.2
80
81 /* can_init_procdir registers the entire CAN directory tree recursively at
82  * the proc system.
83  */
84 int can_init_procdir(void)
85 {
86         int board;
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);
91 #else
92         base->can_proc_entry = create_proc_entry("can", S_IFDIR | S_IRUGO | 
93                                         S_IXUGO, &proc_root);
94 #endif
95         if (base->can_proc_entry == NULL)
96                 return -ENODEV;
97
98         for (board=0; board<hardware_p->nr_boards; board++) {
99                 candev=hardware_p->candevice[board];
100                 if(candev) add_channel_to_procdir(candev);
101         } 
102
103         return 0;
104 }
105
106 /* can_delete_procdir removes the entire CAN tree from the proc system */
107 int can_delete_procdir(void)
108 {
109         if (remove_channel_from_procdir()) 
110                 return -ENODEV;
111 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
112         if (can_remove_proc_entry(base->can_proc_entry, &proc_root)) 
113                 return -ENODEV;
114 #else
115         remove_proc_entry("can", &proc_root);
116 #endif
117
118         return 0;
119 }
120
121 int add_channel_to_procdir(struct candevice_t *candev)
122 {
123         int i=0;
124
125         for (i=0; i < candev->nr_all_chips; i++) {
126
127                 base->channel[cc] = (struct channelproc_t *)
128                         can_checked_malloc(sizeof(struct channelproc_t));
129                 if (base->channel[cc] == NULL)
130                         return -ENOMEM;
131
132                 sprintf(base->channel[cc]->ch_name, "channel%d",cc);
133                                                 
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);
139 #else
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);
144 #endif
145                 if (base->channel[cc]->ch_entry == NULL)
146                         return -ENODEV;
147
148                 add_object_to_procdir(cc);
149
150                 cc++;
151         } 
152
153         return 0;
154 }
155
156 int remove_channel_from_procdir(void)
157 {
158         
159         while (cc != 0) {
160                 cc--;
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))
164                         return -ENODEV;
165 #else
166                 remove_proc_entry(base->channel[cc]->ch_name,
167                                                         base->can_proc_entry);
168 #endif
169                 if (remove_object_from_procdir())
170                         return -ENODEV; 
171         }
172
173         return 0;
174 }
175
176
177 int add_object_to_procdir(int chip_nr)
178 {
179         int i, max_objects;
180
181         max_objects=chips_p[chip_nr]->max_objects;
182
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));
186
187                 if (base->channel[chip_nr]->object[i] == NULL)
188                         return -ENOMEM;
189
190                 sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
191                 sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
192                                                                 
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)
199                         return -ENODEV;
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)
205                         return -ENODEV;
206                 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can");
207                 base->channel[chip_nr]->object[i]->lnk->readlink_proc =
208                                                                 candev_readlink;
209
210 #else
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)
216                         return -ENODEV;
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)
224                         return -ENODEV;
225 #endif
226
227         }
228         return 0;
229
230
231 int remove_object_from_procdir(void)
232 {
233         int i=0, obj=0;
234
235         obj=chips_p[cc]->max_objects;
236
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))       
241                         return -ENODEV;
242                 if (can_remove_proc_entry(
243                                 base->channel[cc]->object[i]->obj_entry,
244                                 base->channel[cc]->ch_entry))
245                         return -ENODEV;
246 #else
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);
251 #endif
252                 
253         }
254         return 0;
255 }
256
257 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
258 static int candev_readlink(struct proc_dir_entry *de, char *page)
259 {
260         int i=0, nchip=0, nobj=0;
261         char chip[20], object[20], tmp[6];
262
263         sprintf(chip, de->parent->parent->name+7);
264         sprintf(object, de->parent->name+6);
265
266         for (i=0; i<MAX_TOT_CHIPS; i++) {
267                 sprintf(tmp,"%d",i);
268                 if (!strcmp(chip,tmp)) {
269                         nchip=i;
270                         break;
271                 }       
272         }
273         for (i=0; i<MAX_MSGOBJS; i++) {
274                 sprintf(tmp,"%d",i);
275                 if (!strcmp(object,tmp)) {
276                         nobj=i;
277                         break;
278                 }
279         }
280
281         return sprintf(page,"/dev/can%d",chips_p[nchip]->msgobj[nobj]->minor );
282 }
283 #endif //End of candev_readlink for kernel 2.2