Changeset 3323

Show
Ignore:
Timestamp:
07/19/99 01:07:36 (15 years ago)
Author:
frodo
Message:

i2c-proc integration

This is based on Kyösti's code, but somewhat enhanced. Most important is
the extension of the i2c_adapter structure, with the new fields which
were before in separate i2cproc_* arrays.

The code seems very nasty, but that is mostly all #ifdef's needed for
the many changes in 2.1 kernels.

Location:
i2c/trunk/kernel
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • i2c/trunk/kernel/i2c-core.c

    r3322 r3323  
    2828#include <linux/errno.h> 
    2929#include <linux/malloc.h> 
     30#include <linux/proc_fs.h> 
    3031#if LINUX_VERSION_CODE >= 0x020135 
    3132#include <linux/init.h> 
     
    3334#define __init  
    3435#endif 
     36#include <linux/version.h> 
     37#ifndef KERNEL_VERSION 
     38#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c)) 
     39#endif 
     40 
     41#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,4)) 
     42#define copy_from_user memcpy_fromfs 
     43#define copy_to_user memcpy_tofs 
     44#else 
     45#include <asm/uaccess.h> 
     46#endif 
    3547 
    3648#include "i2c.h" 
     
    6678/**** debug level */ 
    6779static int i2c_debug=1; 
     80 
     81/* --------------------------------------------------- 
     82 * /proc entries 
     83 *---------------------------------------------------- 
     84 */ 
     85 
     86static int i2cproc_init(void); 
     87static int i2cproc_cleanup(void); 
     88 
     89#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) 
     90static void monitor_bus_i2c(struct inode *inode, int fill); 
     91#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ 
     92 
     93#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     94 
     95static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,  
     96                                loff_t *ppos); 
     97static int read_bus_i2c(char *buf, char **start, off_t offset, int len, 
     98                           int *eof , void *private); 
     99 
     100#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ 
     101 
     102static int i2cproc_bus_read(struct inode * inode, struct file * file, 
     103                            char * buf, int count); 
     104static int read_bus_i2c(char *buf, char **start, off_t offset, int len, 
     105                        int unused); 
     106 
     107static struct proc_dir_entry proc_bus_dir = 
     108  { 
     109    /* low_ino */       0,     /* Set by proc_register_dynamic */ 
     110    /* namelen */       3,  
     111    /* name */          "bus", 
     112    /* mode */          S_IRUGO | S_IXUGO | S_IFDIR, 
     113    /* nlink */         2,     /* Corrected by proc_register[_dynamic] */ 
     114    /* uid */           0, 
     115    /* gid */           0, 
     116    /* size */          0, 
     117#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36)) 
     118    /* ops */           &proc_dir_inode_operations,  
     119#endif 
     120  }; 
     121 
     122static struct proc_dir_entry proc_bus_i2c_dir = 
     123  { 
     124    /* low_ino */       0,     /* Set by proc_register_dynamic */ 
     125    /* namelen */       3,  
     126    /* name */          "i2c", 
     127    /* mode */          S_IRUGO | S_IFREG, 
     128    /* nlink */         1,      
     129    /* uid */           0, 
     130    /* gid */           0, 
     131    /* size */          0, 
     132    /* ops */           NULL, 
     133    /* get_info */      &read_bus_i2c 
     134  }; 
     135 
     136#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     137 
     138/* To implement the dynamic /proc/bus/i2c-? files, we need our own  
     139   implementation of the read hook */ 
     140static struct file_operations i2cproc_operations = { 
     141        NULL, 
     142        i2cproc_bus_read, 
     143}; 
     144 
     145static struct inode_operations i2cproc_inode_operations = { 
     146        &i2cproc_operations 
     147}; 
     148 
     149static int i2cproc_initialized; 
     150 
    68151 
    69152/* ---------------------------------------------------     
     
    127210{ 
    128211        int i; 
     212        char name[8]; 
     213        struct proc_dir_entry *proc_entry; 
    129214 
    130215        for (i = 0; i < I2C_ADAP_MAX; i++) 
     
    151236 
    152237        DEB(printk("i2c: adapter %s registered.\n",adap->name)); 
     238        sprintf(name,"i2c-%d", i); 
     239 
     240        if (i2cproc_initialized) { 
     241 
     242#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     243                proc_entry = create_proc_entry(name,0,proc_bus); 
     244                if (! proc_entry) { 
     245                        printk("i2c-core: Could not create /proc/bus/%s\n", 
     246                               name); 
     247                        return -ENOENT; 
     248                } 
     249                proc_entry->ops = &i2cproc_inode_operations; 
     250#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) 
     251                proc_entry->fill_inode = &monitor_bus_i2c; 
     252#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ 
     253#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ 
     254                if (!(proc_entry = kmalloc(sizeof(struct proc_dir_entry)+ 
     255                                           strlen(name)+1, GFP_KERNEL))) { 
     256                        printk("i2c-core: Out of memory!\n"); 
     257                        return -ENOMEM; 
     258                } 
     259                memset(proc_entry,0,sizeof(struct proc_dir_entry)); 
     260                proc_entry->namelen = strlen(name); 
     261                proc_entry->name = (char *) (proc_entry + 1); 
     262                proc_entry->mode = S_IRUGO | S_IFREG; 
     263                proc_entry->nlink = 1; 
     264                proc_entry->ops = &i2cproc_inode_operations; 
     265         
     266                /* Nasty stuff to keep GCC satisfied */ 
     267                {  
     268                        char *procname; 
     269                        (const char *) procname  = proc_entry->name; 
     270                        strcpy (procname,name); 
     271                } 
     272         
     273                if ((res = proc_register_dynamic(&proc_bus_dir, proc_entry))) { 
     274                        printk("i2c-core: Could not create %s.\n",name); 
     275                        kfree(proc_entry); 
     276                        return res; 
     277                } 
     278         
     279                adapters[i]->proc_entry = proc_entry; 
     280#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     281 
     282                adapters[i]->inode = proc_entry->low_ino; 
     283        } 
     284 
    153285        return 0;        
    154286} 
     
    157289{ 
    158290        int i,j; 
     291#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     292        char name[8]; 
     293#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
    159294 
    160295        for (i = 0; i < I2C_ADAP_MAX; i++) 
     
    162297                        break; 
    163298        if (I2C_ADAP_MAX == i) { 
    164                 printk(KERN_WARNING  
    165                        " i2c: unregister_adapter adap [%s] not found.\n", 
     299                printk( " i2c: unregister_adapter adap [%s] not found.\n", 
    166300                        adap->name); 
    167301                return -ENODEV; 
     302        } 
     303 
     304        if (i2cproc_initialized) { 
     305#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     306                sprintf(name,"i2c-%d", i); 
     307                remove_proc_entry(name,proc_bus); 
     308#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ 
     309                if ((res = proc_unregister(&proc_bus_dir, 
     310                                           adapters[i]->proc_entry->low_ino))) { 
     311                        printk("i2c-core: Deregistration of /proc " 
     312                               "entry failed\n" 
     313                        return res; 
     314                } 
     315                kfree(adapters[i]->proc_entry); 
     316#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
    168317        } 
    169318 
     
    335484                client->adapter->dec_use(client->adapter); 
    336485} 
     486 
     487/* ---------------------------------------------------- 
     488 * The /proc functions 
     489 * ---------------------------------------------------- 
     490 */ 
     491 
     492#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) 
     493/* Monitor access to /proc/bus/i2c*; make unloading i2c-proc impossible 
     494   if some process still uses it or some file in it */ 
     495void monitor_bus_i2c(struct inode *inode, int fill) 
     496{ 
     497  if (fill) 
     498    MOD_INC_USE_COUNT; 
     499  else 
     500    MOD_DEC_USE_COUNT; 
     501} 
     502#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */ 
     503 
     504/* This function generates the output for /proc/bus/i2c */ 
     505#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     506int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,  
     507                 void *private) 
     508#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ 
     509int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused) 
     510#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     511{ 
     512  int i; 
     513  int nr = 0; 
     514  /* Note that it is safe to write a `little' beyond len. Yes, really. */ 
     515  for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++) 
     516    if (adapters[i]) 
     517      nr += sprintf(buf+nr, "i2c-%d\t", i2c_adapter_id(adapters[i])); 
     518      if (adapters[i]->algo->smbus_xfer) { 
     519        if (adapters[i]->algo->master_xfer) 
     520          nr += sprintf(buf+nr,"smbus/i2c"); 
     521        else 
     522          nr += sprintf(buf+nr,"smbus    "); 
     523      } else if (adapters[i]->algo->master_xfer) 
     524         nr += sprintf(buf+nr,"i2c       "); 
     525      else 
     526         nr += sprintf(buf+nr,"dummy     "); 
     527      nr += sprintf(buf+nr,"\t%-32s\t%-32s\n", 
     528                    adapters[i]->name, 
     529                    adapters[i]->algo->name); 
     530  return nr; 
     531} 
     532 
     533/* This function generates the output for /proc/bus/i2c-? */ 
     534#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     535ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,  
     536                         loff_t *ppos) 
     537{ 
     538  struct inode * inode = file->f_dentry->d_inode; 
     539#else (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) 
     540int i2cproc_bus_read(struct inode * inode, struct file * file,char * buf, 
     541                     int count) 
     542{ 
     543#endif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     544  char *kbuf; 
     545  struct i2c_client *client; 
     546  int i,j,len=0; 
     547 
     548  if (count < 0) 
     549    return -EINVAL; 
     550  if (count > 4000) 
     551    count = 4000; 
     552  for (i = 0; i < I2C_ADAP_MAX; i++) 
     553    if (adapters[i]->inode == inode->i_ino) { 
     554      /* We need a bit of slack in the kernel buffer; this makes the 
     555         sprintf safe. */ 
     556      if (! (kbuf = kmalloc(count + 80,GFP_KERNEL))) 
     557        return -ENOMEM; 
     558      for (j = 0; j < I2C_CLIENT_MAX; j++) 
     559        if ((client = adapters[i]->clients[j])) 
     560          /* Filter out dummy clients */ 
     561          if (client->driver->id != I2C_DRIVERID_I2CDEV) 
     562            len += sprintf(kbuf+len,"%x\t%-32s\t%-32s\n", 
     563                           client->addr, 
     564                           client->name,client->driver->name); 
     565      if (file->f_pos+len > count) 
     566        len = count - file->f_pos; 
     567      len = len - file->f_pos; 
     568      if (len < 0)  
     569        len = 0; 
     570      copy_to_user (buf,kbuf+file->f_pos,len); 
     571      file->f_pos += len; 
     572      kfree(kbuf); 
     573      return len; 
     574    } 
     575  return -ENOENT; 
     576} 
     577 
     578int i2cproc_init(void) 
     579{ 
     580 
     581#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     582        struct proc_dir_entry *proc_bus_i2c; 
     583#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     584 
     585        i2cproc_initialized = 0; 
     586 
     587#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     588        if (! proc_bus) { 
     589                printk("i2c-core: /proc/bus/ does not exist"); 
     590                i2cproc_cleanup(); 
     591                return -ENOENT; 
     592        }  
     593        proc_bus_i2c = create_proc_entry("i2c",0,proc_bus); 
     594        if (!proc_bus_i2c) { 
     595                printk("i2c-core: Could not create /proc/bus/i2c"); 
     596                i2cproc_cleanup(); 
     597                return -ENOENT; 
     598        } 
     599        proc_bus_i2c->read_proc = &read_bus_i2c; 
     600#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) 
     601        proc_bus_i2c->fill_inode = &monitor_bus_i2c; 
     602#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     603        i2cproc_initialized += 2; 
     604#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ 
     605        /* In Linux 2.0.x, there is no /proc/bus! But I hope no other module 
     606           introduced it, or we are fucked. And 2.0.35 and earlier does not 
     607           export proc_dir_inode_operations, so we grab it from proc_net, 
     608           which also uses it. Not nice. */ 
     609        proc_bus_dir.ops = proc_net.ops; 
     610        if ((res = proc_register_dynamic(&proc_root, &proc_bus_dir))) { 
     611                printk("i2c-core: Could not create /proc/bus/"); 
     612                i2cproc_cleanup(); 
     613                return res; 
     614        } 
     615        i2cproc_initialized ++; 
     616        if ((res = proc_register_dynamic(&proc_bus_dir, &proc_bus_i2c_dir))) { 
     617                printk("i2c-core: Could not create /proc/bus/i2c\n"); 
     618                i2cproc_cleanup(); 
     619                return res; 
     620        } 
     621        i2cproc_initialized ++; 
     622#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     623        return 0; 
     624} 
     625 
     626int i2cproc_cleanup(void) 
     627{ 
     628 
     629        if (i2cproc_initialized >= 1) { 
     630#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) 
     631                remove_proc_entry("i2c",proc_bus); 
     632                i2cproc_initialized -= 2; 
     633#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */ 
     634                if (i2cproc_initialized >= 2) { 
     635                        if ((res = proc_unregister(&proc_bus_dir, 
     636                                                  proc_bus_i2c_dir.low_ino))) { 
     637                                printk("i2c-core: could not delete " 
     638                                       "/proc/bus/i2c, module not removed."); 
     639                                return res; 
     640                        }     
     641                        i2cproc_initialized --; 
     642                } 
     643                if ((res = proc_unregister(&proc_root,proc_bus_dir.low_ino))) { 
     644                        printk("i2c-core: could not delete /proc/bus/, " 
     645                               "module not removed."); 
     646                        return res; 
     647                }     
     648                i2cproc_initialized --; 
     649#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */ 
     650        } 
     651        return 0; 
     652} 
     653 
    337654 
    338655/* ---------------------------------------------------- 
     
    9081225int init_module(void)  
    9091226{ 
    910         return i2c_init(); 
     1227        int res; 
     1228        res = i2c_init(); 
     1229        if(!res) 
     1230                res = i2cproc_init(); 
     1231        return res;      
    9111232} 
    9121233 
    9131234void cleanup_module(void)  
    9141235{ 
    915 } 
    916 #endif 
     1236        i2cproc_cleanup(); 
     1237} 
     1238#endif 
  • i2c/trunk/kernel/i2c.h

    r3322 r3323  
    231231}; 
    232232 
     233#if LINUX_VERSION_CODE < 0x02011d 
     234struct proc_dir_entry; 
     235#endif 
    233236 
    234237/* 
     
    260263        int timeout; 
    261264        int retries; 
     265 
     266        /* No need to set this when you initialize the adapter          */ 
     267        int inode; 
     268#if LINUX_VERSION_CODE < 0x02011d 
     269        struct proc_dir_entry *proc_entry; 
     270#endif 
    262271}; 
    263272