X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/dce44bcb29b3db78b9e6402d494de3a6891ad74c..98a649bf9242fb74561748a4a15acfa541383738:/lincan/src/proc.c diff --git a/lincan/src/proc.c b/lincan/src/proc.c index 16dda35..34ecc43 100644 --- a/lincan/src/proc.c +++ b/lincan/src/proc.c @@ -61,10 +61,130 @@ static int cc=0; /* static counter for each CAN chip */ 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. - */ -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + +#include + +#define CAN_PROC_SHOW_SINGLE_OPS_DECLARE(ops_name, show_function) \ +static int ops_name##_open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, show_function, PDE_DATA(inode)); \ +} \ +static const struct file_operations ops_name = { \ + .owner = THIS_MODULE, \ + .open = ops_name##_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +}; + +typedef struct file_operations can_proc_read_entry_ops_t; +typedef struct seq_file can_proc_seq_file_t; + +static inline void *can_seq_data(can_proc_seq_file_t *sqf) +{ + return sqf->private; +} + +#define can_seq_printf seq_printf + +struct proc_dir_entry *can_create_proc_read_entry(const char *name, + mode_t mode, struct proc_dir_entry *parent, + const can_proc_read_entry_ops_t *proc_read_entry_ops, void * data) +{ + return proc_create_data(name, mode, parent, proc_read_entry_ops, data); +} + +struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode, + struct proc_dir_entry *parent) +{ + return proc_mkdir_mode(name, mode, parent); +} + +static int can_proc_remove(struct proc_dir_entry *del) +{ + if(!del) return -ENODEV; + proc_remove(del); + 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); +} + +#else /* kernel older than 3.10 */ + +typedef read_proc_t *can_proc_read_entry_ops_t; +typedef struct { + int len; + int limit; + char *buf; + void *private; +} can_proc_seq_file_t; + +#define CAN_PROC_SHOW_SINGLE_OPS_DECLARE(ops_name, show_function) \ +static int ops_name##_show_wrapper(char *buf, char **start, off_t offset, \ + int count, int *eof, void *data) \ +{ \ + can_proc_seq_file_t seq_pos = { .len = 0, .buf = buf, .limit = PAGE_SIZE, \ + .private = data}; \ + *eof = 1; \ + show_function(&seq_pos, data); \ + return seq_pos.len; \ +} \ +const static can_proc_read_entry_ops_t ops_name = ops_name##_show_wrapper; + +static inline void *can_seq_data(can_proc_seq_file_t *sqf) +{ + return sqf->private; +} + +static inline int can_seq_printf(can_proc_seq_file_t *sqf, const char *f, ...) +{ + int ret; + va_list args; + va_start(args, f); + ret = vsnprintf(sqf->buf + sqf->len, sqf->limit - sqf->len, f, args); + sqf->len += ret; + if (sqf->len > sqf->limit) + sqf->len = sqf->limit; + va_end(args); + return ret; +} + +struct proc_dir_entry *can_create_proc_read_entry(const char *name, + mode_t mode, struct proc_dir_entry *parent, + const can_proc_read_entry_ops_t *proc_read_entry_ops, void * data) +{ + return create_proc_read_entry(name, mode, parent, *proc_read_entry_ops, data); +} + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)) + +struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode, + struct proc_dir_entry *parent) +{ + return create_proc_entry(name, S_IFDIR | 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_proc_remove(struct proc_dir_entry *del) +{ + if(!del) return -ENODEV; + remove_proc_entry(del->name, del->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); +} + +#else /* ancient Linux kernel older than 2.3.0 */ static void can_fill_inode(struct inode *inode, int fill) { if (fill) @@ -160,87 +280,9 @@ static inline struct proc_dir_entry *can_proc_symlink(const char *name, return entry; } -#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)) - -struct proc_dir_entry *can_create_proc_read_entry(const char *name, - mode_t mode, struct proc_dir_entry *parent, - read_proc_t *read_proc, void * data) -{ - return create_proc_read_entry(name, mode, parent, read_proc, data); -} - -struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode, - struct proc_dir_entry *parent) -{ - return create_proc_entry(name, S_IFDIR | 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_proc_remove(struct proc_dir_entry *del) -{ - if(!del) return -ENODEV; - remove_proc_entry(del->name, del->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); -} - -#else /* Linux kernel 3.10+ */ +#endif /* Linux 2.2 - 2.3 kernels */ -#include - -static int can_status_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "dummy CAN can_create_proc_read_entry implementation\n"); - return 0; -} - -static int can_status_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, can_status_proc_show, PDE_DATA(inode)); -} - -static const struct file_operations can_status_proc_fops = { - .owner = THIS_MODULE, - .open = can_status_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -struct proc_dir_entry *can_create_proc_read_entry(const char *name, - mode_t mode, struct proc_dir_entry *parent, - void *read_proc, void * data) -{ - /*return proc_read_entry(name, mode, parent, read_proc, data);*/ - return proc_create_data(name, mode, parent, &can_status_proc_fops, data); -} - -struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode, - struct proc_dir_entry *parent) -{ - return proc_mkdir_mode(name, mode, parent); -} - -static int can_proc_remove(struct proc_dir_entry *del) -{ - if(!del) return -ENODEV; - proc_remove(del); - 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 */ +#endif /* Linux kernel 3.6 and 3.10+ */ /* can_init_procdir registers the entire CAN directory tree recursively at * the proc system. @@ -274,24 +316,21 @@ int can_delete_procdir(void) return 0; } -static int can_chip_procinfo(char *buf, char **start, off_t offset, - int count, int *eof, void *data) +static int can_chip_procinfo_show(can_proc_seq_file_t *sqf, void *data) { - struct canchip_t *chip=data; - int len=0; + struct canchip_t *chip=can_seq_data(sqf); /* Generic chip info */ - len += sprintf(buf+len,"type : %s\n",chip->chip_type); - len += sprintf(buf+len,"index : %d\n",chip->chip_idx); - len += sprintf(buf+len,"irq : %d\n",chip->chip_irq); - len += sprintf(buf+len,"addr : %lu\n", + can_seq_printf(sqf, "type : %s\n",chip->chip_type); + can_seq_printf(sqf, "index : %d\n",chip->chip_idx); + can_seq_printf(sqf, "irq : %d\n",chip->chip_irq); + can_seq_printf(sqf, "addr : %lu\n", can_ioptr2ulong(chip->chip_base_addr)); - len += sprintf(buf+len,"config : %s\n", + can_seq_printf(sqf, "config : %s\n", (chip->flags & CHIP_CONFIGURED) ? "yes":"no"); - len += sprintf(buf+len,"clock : %ld Hz\n",chip->clock); - len += sprintf(buf+len,"baud : %ld\n",chip->baudrate); - len += sprintf(buf+len,"num obj : %d\n",chip->max_objects); - + can_seq_printf(sqf, "clock : %ld Hz\n",chip->clock); + can_seq_printf(sqf, "baud : %ld\n",chip->baudrate); + can_seq_printf(sqf, "num obj : %d\n",chip->max_objects); #if 0 /* Chip specific info if available */ @@ -299,10 +338,10 @@ static int can_chip_procinfo(char *buf, char **start, off_t offset, len += (chip->chipspecops->get_info)(chip,buf+len); #endif - *eof = 1; - return len; + return 0; } +CAN_PROC_SHOW_SINGLE_OPS_DECLARE(can_chip_procinfo_ops, can_chip_procinfo_show); int add_channel_to_procdir(struct candevice_t *candev) { @@ -330,7 +369,7 @@ int add_channel_to_procdir(struct candevice_t *candev) can_create_proc_read_entry("chip_info", /* proc entry name */ 0, /* protection mask, 0->default */ base->channel[cc]->ch_entry, /* parent dir, NULL->/proc */ - can_chip_procinfo, + &can_chip_procinfo_ops, candev->chip[i]); cc++;