www.pudn.com > 422.rar > proc.c
/* proc.c * Linux serial-bus device driver. * Written by wang song yue--bupt email:wsy5228@sina.com * This software is released under the GPL-License. * Version 0.1 28 october 2005 */ #define __NO_VERSION__ #include#include #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) #define MODVERSIONS #endif #if defined (MODVERSIONS) #include #endif #include #include #include #include #include "../include/main.h" #include "../include/proc.h" #include "../include/setup.h" int add_channel_to_procdir(void); int remove_channel_from_procdir(void); int add_object_to_procdir(void); int remove_object_from_procdir(void); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) static int candev_readlink(struct proc_dir_entry *de, char *page); #endif static int bc=0; /* static counter for each hardware board */ static int cc=0; /* static counter for each CAN chip */ static int oc=0; /* static counter for each message object */ struct canproc_t can_proc_base; 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. */ #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) static void can_fill_inode(struct inode *inode, int fill) { if (fill) MOD_INC_USE_COUNT; else 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) { struct proc_dir_entry *new_entry = NULL; new_entry = (struct proc_dir_entry *) kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); 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; new_entry->mode = mode; new_entry->nlink = nlink; new_entry->fill_inode = can_fill_inode; new_entry->parent = parent; proc_register(parent, new_entry); return new_entry; } int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent) { if (del != NULL) { proc_unregister(parent, del->low_ino); kfree(del); del = NULL; return 0; } else return -ENODEV; } #endif // Functions required for kernel 2.2 /* can_init_procdir registers the entire CAN directory tree recursively at * the proc system. */ int can_init_procdir(void) { #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) //by wangsy base->can_proc_entry = new_can_proc_entry(0, "tts", S_IFDIR | S_IRUGO | S_IXUGO, 0, &proc_root); #else base->can_proc_entry = create_proc_entry("tts", S_IFDIR | S_IRUGO | S_IXUGO, &proc_root); #endif if (base->can_proc_entry == NULL) return -ENODEV; for (bc=0; bc nr_boards; bc++) { add_channel_to_procdir(); } return 0; } /* can_delete_procdir removes the entire CAN tree from the proc system */ int can_delete_procdir(void) { if (remove_channel_from_procdir()) return -ENODEV; #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) if (can_remove_proc_entry(base->can_proc_entry, &proc_root)) return -ENODEV; #else remove_proc_entry("can", &proc_root); #endif return 0; } int add_channel_to_procdir(void) { int i=0; for (i=0; i nr_16c554_chips; i++) { base->channel[cc] = (struct channelproc_t *) kmalloc(sizeof(struct channelproc_t), GFP_KERNEL); if (base->channel[cc] == NULL) return -ENOMEM; else if (add_mem_to_list(base->channel[cc])) return -ENOMEM; sprintf(base->channel[cc]->ch_name, "channel%d",cc); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) 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_name, S_IFDIR | S_IRUGO |S_IXUGO, base->can_proc_entry); #endif if (base->channel[cc]->ch_entry == NULL) return -ENODEV; add_object_to_procdir(); cc++; } return 0; } int remove_channel_from_procdir(void) { while (cc != 0) { cc--; #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) 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; } return 0; } int add_object_to_procdir(void) { int i=0, obj=0; if (!strcmp(chips_p[cc]->chip_type,"i82527")) obj=15; if (!strcmp(chips_p[cc]->chip_type,"16c554")) obj=1; for (i=0; i channel[cc]->object[i] = (struct objectproc_t *) kmalloc(sizeof(struct objectproc_t),GFP_KERNEL); if (base->channel[cc]->object[i] == NULL) return -ENOMEM; else if (add_mem_to_list( base->channel[cc]->object[i])) return -ENOMEM; sprintf(base->channel[cc]->object[i]->obj_name,"object%d",i); sprintf(base->channel[cc]->object[i]->lnk_name,"dev"); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) base->channel[cc]->object[i]->obj_entry=new_can_proc_entry( 0, base->channel[cc]->object[i]->obj_name, S_IFDIR | S_IRUGO | S_IXUGO, 0, base->channel[cc]->ch_entry); if (base->channel[cc]->object[i]->obj_entry == NULL) return -ENODEV; base->channel[cc]->object[i]->lnk = new_can_proc_entry( 0, base->channel[cc]->object[i]->lnk_name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 0, base->channel[cc]->object[i]->obj_entry); if (base->channel[cc]->object[i]->lnk == NULL) return -ENODEV; sprintf(base->channel[cc]->object[i]->lnk_dev,"/dev/tts"); base->channel[cc]->object[i]->lnk->readlink_proc = candev_readlink; #else base->channel[cc]->object[i]->obj_entry = create_proc_entry( base->channel[cc]->object[i]->obj_name, S_IFDIR | S_IRUGO | S_IXUGO, base->channel[cc]->ch_entry); if (base->channel[cc]->object[i]->obj_entry == NULL) return -ENODEV; sprintf(base->channel[cc]->object[i]->lnk_dev,"/dev/tts%d", //by wangsy chips_p[cc]->msgobj[i]->minor); base->channel[cc]->object[i]->lnk = proc_symlink( base->channel[cc]->object[i]->lnk_name, base->channel[cc]->object[i]->obj_entry, base->channel[cc]->object[i]->lnk_dev); if (base->channel[cc]->object[i]->lnk == NULL) return -ENODEV; #endif } return 0; } int remove_object_from_procdir(void) { int i=0, obj=0; if (!strcmp(chips_p[cc]->chip_type,"i82527")) obj=15; if (!strcmp(chips_p[cc]->chip_type,"16c554")) obj=1; for (i=0; i channel[cc]->object[i]->lnk, base->channel[cc]->object[i]->obj_entry)) return -ENODEV; if (can_remove_proc_entry( base->channel[cc]->object[i]->obj_entry, base->channel[cc]->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 } return 0; } #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,2,19)) 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 msgobj[nobj]->minor ); //by wangsy } #endif //End of candev_readlink for kernel 2.2