Cleaned-up PROC handling and checked on 2.4, 2.4-RT, 2.6 and compilation for 2.2...
authorppisa <ppisa>
Tue, 16 Mar 2004 16:14:52 +0000 (16:14 +0000)
committerppisa <ppisa>
Tue, 16 Mar 2004 16:14:52 +0000 (16:14 +0000)
lincan/src/Makefile.std
lincan/src/proc.c

index f740504..40dacc3 100644 (file)
@@ -122,6 +122,12 @@ ifdef PROC_FS
        O_OBJS += proc.o
 endif
 
+ifdef SUBDIRS
+EXTRA_CFLAGS += -I $(SUBDIRS)
+else
+EXTRA_CFLAGS += -I .
+endif
+
 # Target object file if any
 # this must be undefined for 2.5.xx kernels
 ifndef KERNEL_MODULE_V26
@@ -145,7 +151,7 @@ L_OBJS       =
 # Kernel only objects with exported symbols (-DEXPORT_SYMTAB)
 LX_OBJS      = 
 # Additional CFLAGS
-EXTRA_CFLAGS += -I .
+EXTRA_CFLAGS +=
 
 # Linux 2.4.2 and newer build system needs next
 can-objs = $(O_OBJS)
index 254aabc..02522b1 100644 (file)
 int add_channel_to_procdir(struct candevice_t *candev);
 int remove_channel_from_procdir(void);
 int add_object_to_procdir(int chip_nr);
-int remove_object_from_procdir(void);
+int remove_object_from_procdir(int chip_nr);
 
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-static int candev_readlink(struct proc_dir_entry *de, char *page);
+static int can_proc_readlink(struct proc_dir_entry *ent, char *page);
 #endif
 
 static int cc=0; /* static counter for each CAN chip */
 
-struct canproc_t can_proc_base;
-struct canproc_t *base=&can_proc_base;
+static struct canproc_t can_proc_base;
+static struct canproc_t *base=&can_proc_base;
 
 /* The following functions are needed only for kernel version 2.2. Kernel
  * version 2.4 already defines them for us.
@@ -42,23 +42,36 @@ static void can_fill_inode(struct inode *inode, int fill)
                MOD_DEC_USE_COUNT;
 }
 
-static struct proc_dir_entry * new_can_proc_entry(unsigned short inode,
-    const char *name, mode_t mode, nlink_t nlink, struct proc_dir_entry *parent)
+static struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
+                                       struct proc_dir_entry *parent)
 {
        struct proc_dir_entry *new_entry = NULL;
+       char *namestore;
+       int namelen;
+       
+       if(!name || !parent)
+               return NULL;
+       namelen=strlen(name);
+       if(!namelen)
+               return NULL;
 
        new_entry = (struct proc_dir_entry *) 
-                       can_checked_malloc(sizeof(struct proc_dir_entry));
+                       can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
+
        if (new_entry == NULL)
                return NULL;
 
        memset(new_entry, 0, sizeof(struct proc_dir_entry));
 
-       new_entry->low_ino = inode;
-       new_entry->namelen = strlen(name);
-       new_entry->name = name;
+       /* Store copy of the proc entry name */
+       namestore = ((char *) new_entry) + sizeof(struct proc_dir_entry);
+       memcpy(namestore, name, namelen + 1);
+
+       new_entry->low_ino = 0;
+       new_entry->namelen = namelen;
+       new_entry->name = namestore;
        new_entry->mode = mode;
-       new_entry->nlink = nlink;
+       new_entry->nlink = 0;
        new_entry->fill_inode = can_fill_inode;
        new_entry->parent = parent;
 
@@ -67,7 +80,7 @@ static struct proc_dir_entry * new_can_proc_entry(unsigned short inode,
        return new_entry;
 }
 
-int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
+static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
 {
        if (del != NULL) {
                proc_unregister(parent, del->low_ino);
@@ -76,7 +89,58 @@ int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *par
        }
        else return -ENODEV;
 }
-#endif // Functions required for kernel 2.2
+
+
+static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
+{
+       char *link_dest = (char*)ent->data;
+       
+       strcpy(page, link_dest);
+       return strlen(link_dest);
+}
+
+
+
+/* This compatibility version of proc_symlink does not store local copy of destination */
+static inline struct proc_dir_entry *can_proc_symlink(const char *name,
+                struct proc_dir_entry *parent, const char *dest)
+{
+       struct proc_dir_entry *entry;
+       
+       
+       entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
+       if (entry == NULL)
+               return NULL;
+       entry->readlink_proc = can_proc_readlink;
+       entry->data = dest;
+       return entry;
+}
+
+#else /* Functions forwarded for kernel 2.4 and above */
+
+static inline struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
+                                       struct proc_dir_entry *parent)
+{
+       return create_proc_entry(name, mode, parent);
+}
+
+
+/* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */
+/* The newer kernels use entry name instead of pointer to the entry */
+static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
+{
+       if(!del) return -ENODEV;
+       remove_proc_entry(del->name,parent);
+       return 0;
+}
+
+static inline struct proc_dir_entry *can_proc_symlink(const char *name,
+                struct proc_dir_entry *parent, const char *dest)
+{
+       return proc_symlink(name, parent, dest);
+}
+
+#endif /* Functions required for kernel 2.2 */
 
 /* can_init_procdir registers the entire CAN directory tree recursively at
  * the proc system.
@@ -85,13 +149,8 @@ int can_init_procdir(void)
 {
        int board;
        struct candevice_t *candev;
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-       base->can_proc_entry = new_can_proc_entry(0, "can", S_IFDIR | S_IRUGO | 
-                                       S_IXUGO, 0, &proc_root);
-#else
-       base->can_proc_entry = create_proc_entry("can", S_IFDIR | S_IRUGO | 
+       base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO | 
                                        S_IXUGO, &proc_root);
-#endif
        if (base->can_proc_entry == NULL)
                return -ENODEV;
 
@@ -108,12 +167,9 @@ int can_delete_procdir(void)
 {
        if (remove_channel_from_procdir()) 
                return -ENODEV;
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
+       /* name: "can" */
        if (can_remove_proc_entry(base->can_proc_entry, &proc_root)) 
                return -ENODEV;
-#else
-       remove_proc_entry("can", &proc_root);
-#endif
 
        return 0;
 }
@@ -131,17 +187,11 @@ int add_channel_to_procdir(struct candevice_t *candev)
 
                sprintf(base->channel[cc]->ch_name, "channel%d",cc);
                                                
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-               base->channel[cc]->ch_entry = new_can_proc_entry(0, 
-                                               base->channel[cc]->ch_name,
-                                               S_IFDIR | S_IRUGO | S_IXUGO, 0, 
-                                               base->can_proc_entry);
-#else
-               base->channel[cc]->ch_entry = create_proc_entry(
+               base->channel[cc]->ch_entry = can_create_proc_entry(
                                                base->channel[cc]->ch_name,
                                                S_IFDIR | S_IRUGO |S_IXUGO,
                                                base->can_proc_entry);
-#endif
+
                if (base->channel[cc]->ch_entry == NULL)
                        return -ENODEV;
 
@@ -158,16 +208,19 @@ int remove_channel_from_procdir(void)
        
        while (cc != 0) {
                cc--;
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
+               
+               if(!base->channel[cc]) continue;
+               
+               if (remove_object_from_procdir(cc))
+                       return -ENODEV; 
+                       
+               /* name: base->channel[cc]->ch_name */
                if (can_remove_proc_entry(base->channel[cc]->ch_entry,
                                                        base->can_proc_entry))
                        return -ENODEV;
-#else
-               remove_proc_entry(base->channel[cc]->ch_name,
-                                                       base->can_proc_entry);
-#endif
-               if (remove_object_from_procdir())
-                       return -ENODEV; 
+                       
+               can_checked_free(base->channel[cc]);
+               base->channel[cc] = NULL;
        }
 
        return 0;
@@ -190,94 +243,50 @@ int add_object_to_procdir(int chip_nr)
                sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
                sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
                                                                
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-               base->channel[chip_nr]->object[i]->obj_entry=new_can_proc_entry(
-                               0, base->channel[chip_nr]->object[i]->obj_name,
-                               S_IFDIR | S_IRUGO | S_IXUGO, 0, 
-                               base->channel[chip_nr]->ch_entry);
-               if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
-                       return -ENODEV;
-               base->channel[chip_nr]->object[i]->lnk = new_can_proc_entry(
-                               0, base->channel[chip_nr]->object[i]->lnk_name, 
-                               S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO,
-                               0, base->channel[chip_nr]->object[i]->obj_entry);
-               if (base->channel[chip_nr]->object[i]->lnk == NULL)
-                       return -ENODEV;
-               sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can");
-               base->channel[chip_nr]->object[i]->lnk->readlink_proc =
-                                                               candev_readlink;
-
-#else
-               base->channel[chip_nr]->object[i]->obj_entry = create_proc_entry(
+               base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry(
                                base->channel[chip_nr]->object[i]->obj_name,
                                S_IFDIR | S_IRUGO | S_IXUGO,
                                base->channel[chip_nr]->ch_entry);
                if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
                        return -ENODEV;
+
                sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
                        chips_p[chip_nr]->msgobj[i]->minor);
-               base->channel[chip_nr]->object[i]->lnk = proc_symlink(
+
+               base->channel[chip_nr]->object[i]->lnk = can_proc_symlink(
                                base->channel[chip_nr]->object[i]->lnk_name,
                                base->channel[chip_nr]->object[i]->obj_entry,
                                base->channel[chip_nr]->object[i]->lnk_dev);
                if (base->channel[chip_nr]->object[i]->lnk == NULL)
                        return -ENODEV;
-#endif
 
        }
        return 0;
 } 
 
-int remove_object_from_procdir(void)
+int remove_object_from_procdir(int chip_nr)
 {
        int i=0, obj=0;
 
-       obj=chips_p[cc]->max_objects;
+       obj=chips_p[chip_nr]->max_objects;
 
        for (i=0; i<obj; i++) {
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-               if (can_remove_proc_entry( base->channel[cc]->object[i]->lnk,
-                               base->channel[cc]->object[i]->obj_entry))       
+               if(!base->channel[chip_nr]->object[i]) continue;
+               
+               /* name: base->channel[chip_nr]->object[i]->lnk_name */
+               if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk,
+                               base->channel[chip_nr]->object[i]->obj_entry))  
                        return -ENODEV;
+               /* name: base->channel[chip_nr]->object[i]->obj_name */
                if (can_remove_proc_entry(
-                               base->channel[cc]->object[i]->obj_entry,
-                               base->channel[cc]->ch_entry))
+                               base->channel[chip_nr]->object[i]->obj_entry,
+                               base->channel[chip_nr]->ch_entry))
                        return -ENODEV;
-#else
-               remove_proc_entry(base->channel[cc]->object[i]->lnk_name,
-                               base->channel[cc]->object[i]->obj_entry);
-               remove_proc_entry(base->channel[cc]->object[i]->obj_name,
-                                       base->channel[cc]->ch_entry);
-#endif
-               
+
+               can_checked_free(base->channel[chip_nr]->object[i]);
+
+               base->channel[chip_nr]->object[i]=NULL;
        }
        return 0;
 }
 
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-static int candev_readlink(struct proc_dir_entry *de, char *page)
-{
-       int i=0, nchip=0, nobj=0;
-       char chip[20], object[20], tmp[6];
-
-       sprintf(chip, de->parent->parent->name+7);
-       sprintf(object, de->parent->name+6);
-
-       for (i=0; i<MAX_TOT_CHIPS; i++) {
-               sprintf(tmp,"%d",i);
-               if (!strcmp(chip,tmp)) {
-                       nchip=i;
-                       break;
-               }       
-       }
-       for (i=0; i<MAX_MSGOBJS; i++) {
-               sprintf(tmp,"%d",i);
-               if (!strcmp(object,tmp)) {
-                       nobj=i;
-                       break;
-               }
-       }
-
-       return sprintf(page,"/dev/can%d",chips_p[nchip]->msgobj[nobj]->minor );
-}
-#endif //End of candev_readlink for kernel 2.2