root/i2c/branches/lk2-4/kernel/i2c-proc.c @ 3782

Revision 3782, 22.0 KB (checked in by mmh, 10 years ago)

Backport of patch proposed by Chistoph Hellwig on LKML 3/12/03.
(mmh) This fixes an oops during client registration.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    i2c-proc.c - Part of lm_sensors, Linux kernel modules for hardware
3                monitoring
4    Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
5    Mark D. Studebaker <mdsxyz123@yahoo.com>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22/*
23    This driver puts entries in /proc/sys/dev/sensors for each I2C device
24*/
25
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/ctype.h>
30#include <linux/sysctl.h>
31#include <linux/proc_fs.h>
32#include <linux/init.h>
33#include <linux/ioport.h>
34#include "i2c.h"
35#include "i2c-proc.h"
36#include <asm/uaccess.h>
37
38static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
39                               long *results, int magnitude);
40static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
41                               long *results, int magnitude);
42static int i2c_proc_chips(ctl_table * ctl, int write,
43                              struct file *filp, void *buffer,
44                              size_t * lenp);
45static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
46                                void *oldval, size_t * oldlenp,
47                                void *newval, size_t newlen,
48                                void **context);
49
50#define SENSORS_ENTRY_MAX 20
51static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
52
53static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
54
55static ctl_table i2c_proc_dev_sensors[] = {
56        {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips,
57         &i2c_sysctl_chips},
58        {0}
59};
60
61static ctl_table i2c_proc_dev[] = {
62        {DEV_SENSORS, "sensors", NULL, 0, 0555, i2c_proc_dev_sensors},
63        {0},
64};
65
66
67static ctl_table i2c_proc[] = {
68        {CTL_DEV, "dev", NULL, 0, 0555, i2c_proc_dev},
69        {0}
70};
71
72
73static struct ctl_table_header *i2c_proc_header;
74
75/* This returns a nice name for a new directory; for example lm78-isa-0310
76   (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
77   a LM75 chip on the third i2c bus at address 0x4e). 
78   name is allocated first. */
79static char *generate_name(struct i2c_client *client, const char *prefix)
80{
81        struct i2c_adapter *adapter = client->adapter;
82        int addr = client->addr;
83        char name_buffer[50], *name;
84
85        if (i2c_is_isa_adapter(adapter)) {
86                sprintf(name_buffer, "%s-isa-%04x", prefix, addr);
87        } else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) {
88                int id = i2c_adapter_id(adapter);
89                if (id < 0)
90                        return ERR_PTR(-ENOENT);
91                sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
92        } else {        /* dummy adapter, generate prefix */
93                int end, i;
94
95                sprintf(name_buffer, "%s-", prefix);
96                end = strlen(name_buffer);
97
98                for (i = 0; i < 32; i++) {
99                        if (adapter->algo->name[i] == ' ')
100                                break;
101                        name_buffer[end++] = tolower(adapter->algo->name[i]);
102                }
103
104                name_buffer[end] = 0;
105                sprintf(name_buffer + end, "-%04x", addr);
106        }
107
108        name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
109        if (unlikely(!name))
110                return ERR_PTR(-ENOMEM);
111        strcpy(name, name_buffer);
112        return name;
113}
114
115/* This rather complex function must be called when you want to add an entry
116   to /proc/sys/dev/sensors/chips. It also creates a new directory within
117   /proc/sys/dev/sensors/.
118   ctl_template should be a template of the newly created directory. It is
119   copied in memory. The extra2 field of each file is set to point to client.
120   If any driver wants subdirectories within the newly created directory,
121   this function must be updated!  */
122int i2c_register_entry(struct i2c_client *client, const char *prefix,
123                       struct ctl_table *leaf)
124{
125        struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl;
126        struct ctl_table_header *hdr;
127        struct ctl_table *tmp;
128        const char *name;
129        int id;
130
131        name = generate_name(client, prefix);
132        if (IS_ERR(name))
133                return PTR_ERR(name);
134
135        for (id = 0; id < SENSORS_ENTRY_MAX; id++) {
136                if (!i2c_entries[id])
137                        goto free_slot;
138        }
139
140        goto out_free_name;
141
142 free_slot:
143        tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
144        if (unlikely(!tbl))
145                goto out_free_name;
146        memset(tbl, 0, sizeof(*tbl));
147
148        for (tmp = leaf; tmp->ctl_name; tmp++)
149                tmp->extra2 = client;
150
151        tbl->sensors->ctl_name = id+256;
152        tbl->sensors->procname = name;
153        tbl->sensors->mode = 0555;
154        tbl->sensors->child = leaf;
155
156        tbl->dev->ctl_name = DEV_SENSORS;
157        tbl->dev->procname = "sensors";
158        tbl->dev->mode = 0555;
159        tbl->dev->child = tbl->sensors;
160
161        tbl->root->ctl_name = CTL_DEV;
162        tbl->root->procname = "dev";
163        tbl->root->mode = 0555;
164        tbl->root->child = tbl->dev;
165
166        hdr = register_sysctl_table(tbl->root, 0);
167        if (unlikely(!hdr))
168                goto out_free_tbl;
169
170        i2c_entries[id] = hdr;
171        i2c_clients[id] = client;
172
173        return (id + 256);      /* XXX(hch) why?? */
174
175 out_free_tbl:
176        kfree(tbl);
177 out_free_name:
178        kfree(name);
179        return -ENOMEM;
180}
181
182void i2c_deregister_entry(int id)
183{
184        id -= 256;
185
186        if (i2c_entries[id]) {
187                struct ctl_table_header *hdr = i2c_entries[id];
188                struct ctl_table *tbl = hdr->ctl_table;
189
190                unregister_sysctl_table(hdr);
191                kfree(tbl->child->child->procname);
192                kfree(tbl); /* actually the whole anonymous struct */
193        }
194
195        i2c_entries[id] = NULL;
196        i2c_clients[id] = NULL;
197}
198
199static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
200                       void *buffer, size_t * lenp)
201{
202        char BUF[SENSORS_PREFIX_MAX + 30];
203        int buflen, curbufsize, i;
204        struct ctl_table *client_tbl;
205
206        if (write)
207                return 0;
208
209        /* If buffer is size 0, or we try to read when not at the start, we
210           return nothing. Note that I think writing when not at the start
211           does not work either, but anyway, this is straight from the kernel
212           sources. */
213        if (!*lenp || (filp->f_pos && !write)) {
214                *lenp = 0;
215                return 0;
216        }
217        curbufsize = 0;
218        for (i = 0; i < SENSORS_ENTRY_MAX; i++)
219                if (i2c_entries[i]) {
220                        client_tbl =
221                            i2c_entries[i]->ctl_table->child->child;
222                        buflen =
223                            sprintf(BUF, "%d\t%s\n", client_tbl->ctl_name,
224                                    client_tbl->procname);
225                        if (buflen + curbufsize > *lenp)
226                                buflen = *lenp - curbufsize;
227                        if(copy_to_user(buffer, BUF, buflen))
228                                return -EFAULT;
229                        curbufsize += buflen;
230                        (char *) buffer += buflen;
231                }
232        *lenp = curbufsize;
233        filp->f_pos += curbufsize;
234        return 0;
235}
236
237static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
238                         void *oldval, size_t * oldlenp, void *newval,
239                         size_t newlen, void **context)
240{
241        struct i2c_chips_data data;
242        int i, oldlen, nrels, maxels,ret=0;
243        struct ctl_table *client_tbl;
244
245        if (oldval && oldlenp && !((ret = get_user(oldlen, oldlenp))) && 
246            oldlen) {
247                maxels = oldlen / sizeof(struct i2c_chips_data);
248                nrels = 0;
249                for (i = 0; (i < SENSORS_ENTRY_MAX) && (nrels < maxels);
250                     i++)
251                        if (i2c_entries[i]) {
252                                client_tbl =
253                                    i2c_entries[i]->ctl_table->child->
254                                    child;
255                                data.sysctl_id = client_tbl->ctl_name;
256                                strcpy(data.name, client_tbl->procname);
257                                if(copy_to_user(oldval, &data,
258                                             sizeof(struct
259                                                    i2c_chips_data)))
260                                        return -EFAULT;
261                                (char *) oldval +=
262                                    sizeof(struct i2c_chips_data);
263                                nrels++;
264                        }
265                oldlen = nrels * sizeof(struct i2c_chips_data);
266                if(put_user(oldlen, oldlenp))
267                        return -EFAULT;
268        }
269        return ret;
270}
271
272
273/* This funcion reads or writes a 'real' value (encoded by the combination
274   of an integer and a magnitude, the last is the power of ten the value
275   should be divided with) to a /proc/sys directory. To use this function,
276   you must (before registering the ctl_table) set the extra2 field to the
277   client, and the extra1 field to a function of the form:
278      void func(struct i2c_client *client, int operation, int ctl_name,
279                int *nrels_mag, long *results)
280   This function can be called for three values of operation. If operation
281   equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in
282   nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
283   be read into results. nrels_mag should return the number of elements
284   read; the maximum number is put in it on entry. Finally, if operation
285   equals SENSORS_PROC_REAL_WRITE, the values in results should be
286   written to the chip. nrels_mag contains on entry the number of elements
287   found.
288   In all cases, client points to the client we wish to interact with,
289   and ctl_name is the SYSCTL id of the file we are accessing. */
290int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
291                      void *buffer, size_t * lenp)
292{
293#define MAX_RESULTS 32
294        int mag, nrels = MAX_RESULTS;
295        long results[MAX_RESULTS];
296        i2c_real_callback callback = ctl->extra1;
297        struct i2c_client *client = ctl->extra2;
298        int res;
299
300        /* If buffer is size 0, or we try to read when not at the start, we
301           return nothing. Note that I think writing when not at the start
302           does not work either, but anyway, this is straight from the kernel
303           sources. */
304        if (!*lenp || (filp->f_pos && !write)) {
305                *lenp = 0;
306                return 0;
307        }
308
309        /* Get the magnitude */
310        callback(client, SENSORS_PROC_REAL_INFO, ctl->ctl_name, &mag,
311                 NULL);
312
313        if (write) {
314                /* Read the complete input into results, converting to longs */
315                res = i2c_parse_reals(&nrels, buffer, *lenp, results, mag);
316                if (res)
317                        return res;
318
319                if (!nrels)
320                        return 0;
321
322                /* Now feed this information back to the client */
323                callback(client, SENSORS_PROC_REAL_WRITE, ctl->ctl_name,
324                         &nrels, results);
325
326                filp->f_pos += *lenp;
327                return 0;
328        } else {                /* read */
329                /* Get the information from the client into results */
330                callback(client, SENSORS_PROC_REAL_READ, ctl->ctl_name,
331                         &nrels, results);
332
333                /* And write them to buffer, converting to reals */
334                res = i2c_write_reals(nrels, buffer, lenp, results, mag);
335                if (res)
336                        return res;
337                filp->f_pos += *lenp;
338                return 0;
339        }
340}
341
342/* This function is equivalent to i2c_proc_real, only it interacts with
343   the sysctl(2) syscall, and returns no reals, but integers */
344int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
345                        void *oldval, size_t * oldlenp, void *newval,
346                        size_t newlen, void **context)
347{
348        long results[MAX_RESULTS];
349        int oldlen, nrels = MAX_RESULTS,ret=0;
350        i2c_real_callback callback = table->extra1;
351        struct i2c_client *client = table->extra2;
352
353        /* Check if we need to output the old values */
354        if (oldval && oldlenp && !((ret=get_user(oldlen, oldlenp))) && oldlen) {
355                callback(client, SENSORS_PROC_REAL_READ, table->ctl_name,
356                         &nrels, results);
357
358                /* Note the rounding factor! */
359                if (nrels * sizeof(long) < oldlen)
360                        oldlen = nrels * sizeof(long);
361                oldlen = (oldlen / sizeof(long)) * sizeof(long);
362                if(copy_to_user(oldval, results, oldlen))
363                        return -EFAULT;
364                if(put_user(oldlen, oldlenp))
365                        return -EFAULT;
366        }
367
368        if (newval && newlen) {
369                /* Note the rounding factor! */
370                newlen -= newlen % sizeof(long);
371                nrels = newlen / sizeof(long);
372                if(copy_from_user(results, newval, newlen))
373                        return -EFAULT;
374
375                /* Get the new values back to the client */
376                callback(client, SENSORS_PROC_REAL_WRITE, table->ctl_name,
377                         &nrels, results);
378        }
379        return ret;
380}
381
382
383/* nrels contains initially the maximum number of elements which can be
384   put in results, and finally the number of elements actually put there.
385   A magnitude of 1 will multiply everything with 10; etc.
386   buffer, bufsize is the character buffer we read from and its length.
387   results will finally contain the parsed integers.
388
389   Buffer should contain several reals, separated by whitespace. A real
390   has the following syntax:
391     [ Minus ] Digit* [ Dot Digit* ]
392   (everything between [] is optional; * means zero or more).
393   When the next character is unparsable, everything is skipped until the
394   next whitespace.
395
396   WARNING! This is tricky code. I have tested it, but there may still be
397            hidden bugs in it, even leading to crashes and things!
398*/
399static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
400                         long *results, int magnitude)
401{
402        int maxels, min, mag;
403        long res,ret=0;
404        char nextchar = 0;
405
406        maxels = *nrels;
407        *nrels = 0;
408
409        while (bufsize && (*nrels < maxels)) {
410
411                /* Skip spaces at the start */
412                while (bufsize && 
413                       !((ret=get_user(nextchar, (char *) buffer))) &&
414                       isspace((int) nextchar)) {
415                        bufsize--;
416                        ((char *) buffer)++;
417                }
418
419                if (ret)
420                        return -EFAULT; 
421                /* Well, we may be done now */
422                if (!bufsize)
423                        return 0;
424
425                /* New defaults for our result */
426                min = 0;
427                res = 0;
428                mag = magnitude;
429
430                /* Check for a minus */
431                if (!((ret=get_user(nextchar, (char *) buffer)))
432                    && (nextchar == '-')) {
433                        min = 1;
434                        bufsize--;
435                        ((char *) buffer)++;
436                }
437                if (ret)
438                        return -EFAULT;
439
440                /* Digits before a decimal dot */
441                while (bufsize && 
442                       !((ret=get_user(nextchar, (char *) buffer))) &&
443                       isdigit((int) nextchar)) {
444                        res = res * 10 + nextchar - '0';
445                        bufsize--;
446                        ((char *) buffer)++;
447                }
448                if (ret)
449                        return -EFAULT;
450
451                /* If mag < 0, we must actually divide here! */
452                while (mag < 0) {
453                        res = res / 10;
454                        mag++;
455                }
456
457                if (bufsize && (nextchar == '.')) {
458                        /* Skip the dot */
459                        bufsize--;
460                        ((char *) buffer)++;
461
462                        /* Read digits while they are significant */
463                        while (bufsize && (mag > 0) &&
464                               !((ret=get_user(nextchar, (char *) buffer))) &&
465                               isdigit((int) nextchar)) {
466                                res = res * 10 + nextchar - '0';
467                                mag--;
468                                bufsize--;
469                                ((char *) buffer)++;
470                        }
471                        if (ret)
472                                return -EFAULT;
473                }
474                /* If we are out of data, but mag > 0, we need to scale here */
475                while (mag > 0) {
476                        res = res * 10;
477                        mag--;
478                }
479
480                /* Skip everything until we hit whitespace */
481                while (bufsize && 
482                       !((ret=get_user(nextchar, (char *) buffer))) &&
483                       isspace((int) nextchar)) {
484                        bufsize--;
485                        ((char *) buffer)++;
486                }
487                if (ret)
488                        return -EFAULT;
489
490                /* Put res in results */
491                results[*nrels] = (min ? -1 : 1) * res;
492                (*nrels)++;
493        }
494
495        /* Well, there may be more in the buffer, but we need no more data.
496           Ignore anything that is left. */
497        return 0;
498}
499
500static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
501                         long *results, int magnitude)
502{
503#define BUFLEN 20
504        char BUF[BUFLEN + 1];   /* An individual representation should fit! */
505        char printfstr[10];
506        int nr = 0;
507        int buflen, mag, times;
508        int curbufsize = 0;
509
510        while ((nr < nrels) && (curbufsize < *bufsize)) {
511                mag = magnitude;
512
513                if (nr != 0) {
514                        if(put_user(' ', (char *) buffer))
515                                return -EFAULT;
516                        curbufsize++;
517                        ((char *) buffer)++;
518                }
519
520                /* Fill BUF with the representation of the next string */
521                if (mag <= 0) {
522                        buflen = sprintf(BUF, "%ld", results[nr]);
523                        if (buflen < 0) {       /* Oops, a sprintf error! */
524                                *bufsize = 0;
525                                return -EINVAL;
526                        }
527                        while ((mag < 0) && (buflen < BUFLEN)) {
528                                BUF[buflen++] = '0';
529                                mag++;
530                        }
531                        BUF[buflen] = 0;
532                } else {
533                        times = 1;
534                        for (times = 1; mag-- > 0; times *= 10);
535                        if (results[nr] < 0) {
536                                BUF[0] = '-';
537                                buflen = 1;
538                        } else
539                                buflen = 0;
540                        strcpy(printfstr, "%ld.%0Xld");
541                        printfstr[6] = magnitude + '0';
542                        buflen +=
543                            sprintf(BUF + buflen, printfstr,
544                                    abs(results[nr]) / times,
545                                    abs(results[nr]) % times);
546                        if (buflen < 0) {       /* Oops, a sprintf error! */
547                                *bufsize = 0;
548                                return -EINVAL;
549                        }
550                }
551
552                /* Now copy it to the user-space buffer */
553                if (buflen + curbufsize > *bufsize)
554                        buflen = *bufsize - curbufsize;
555                if(copy_to_user(buffer, BUF, buflen))
556                        return -EFAULT;
557                curbufsize += buflen;
558                (char *) buffer += buflen;
559
560                nr++;
561        }
562        if (curbufsize < *bufsize) {
563                if(put_user('\n', (char *) buffer))
564                        return -EFAULT;
565                curbufsize++;
566        }
567        *bufsize = curbufsize;
568        return 0;
569}
570
571
572/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
573int i2c_detect(struct i2c_adapter *adapter,
574                   struct i2c_address_data *address_data,
575                   i2c_found_addr_proc * found_proc)
576{
577        int addr, i, found, j, err;
578        struct i2c_force_data *this_force;
579        int is_isa = i2c_is_isa_adapter(adapter);
580        int adapter_id =
581            is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter);
582
583        /* Forget it if we can't probe using SMBUS_QUICK */
584        if ((!is_isa)
585            && !i2c_check_functionality(adapter,
586                                        I2C_FUNC_SMBUS_QUICK)) return -1;
587
588        for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
589                /* XXX: WTF is going on here??? */
590                if ((is_isa && check_region(addr, 1)) ||
591                    (!is_isa && i2c_check_addr(adapter, addr)))
592                        continue;
593
594                /* If it is in one of the force entries, we don't do any
595                   detection at all */
596                found = 0;
597                for (i = 0;
598                     !found
599                     && (this_force =
600                         address_data->forces + i, this_force->force); i++) {
601                        for (j = 0;
602                             !found
603                             && (this_force->force[j] != SENSORS_I2C_END);
604                             j += 2) {
605                                if (
606                                    ((adapter_id == this_force->force[j])
607                                     ||
608                                     ((this_force->
609                                       force[j] == SENSORS_ANY_I2C_BUS)
610                                      && !is_isa))
611                                    && (addr == this_force->force[j + 1])) {
612#ifdef DEBUG
613                                        printk
614                                            (KERN_DEBUG "i2c-proc.o: found force parameter for adapter %d, addr %04x\n",
615                                             adapter_id, addr);
616#endif
617                                        if (
618                                            (err =
619                                             found_proc(adapter, addr, 0,
620                                                        this_force->
621                                                        kind))) return err;
622                                        found = 1;
623                                }
624                        }
625                }
626                if (found)
627                        continue;
628
629                /* If this address is in one of the ignores, we can forget about it
630                   right now */
631                for (i = 0;
632                     !found
633                     && (address_data->ignore[i] != SENSORS_I2C_END);
634                     i += 2) {
635                        if (
636                            ((adapter_id == address_data->ignore[i])
637                             ||
638                             ((address_data->
639                               ignore[i] == SENSORS_ANY_I2C_BUS)
640                              && !is_isa))
641                            && (addr == address_data->ignore[i + 1])) {
642#ifdef DEBUG
643                                printk
644                                    (KERN_DEBUG "i2c-proc.o: found ignore parameter for adapter %d, "
645                                     "addr %04x\n", adapter_id, addr);
646#endif
647                                found = 1;
648                        }
649                }
650                for (i = 0;
651                     !found
652                     && (address_data->ignore_range[i] != SENSORS_I2C_END);
653                     i += 3) {
654                        if (
655                            ((adapter_id == address_data->ignore_range[i])
656                             ||
657                             ((address_data->
658                               ignore_range[i] ==
659                               SENSORS_ANY_I2C_BUS) & !is_isa))
660                            && (addr >= address_data->ignore_range[i + 1])
661                            && (addr <= address_data->ignore_range[i + 2])) {
662#ifdef DEBUG
663                                printk
664                                    (KERN_DEBUG "i2c-proc.o: found ignore_range parameter for adapter %d, "
665                                     "addr %04x\n", adapter_id, addr);
666#endif
667                                found = 1;
668                        }
669                }
670                if (found)
671                        continue;
672
673                /* Now, we will do a detection, but only if it is in the normal or
674                   probe entries */
675                if (is_isa) {
676                        for (i = 0;
677                             !found
678                             && (address_data->normal_isa[i] !=
679                                 SENSORS_ISA_END); i += 1) {
680                                if (addr == address_data->normal_isa[i]) {
681#ifdef DEBUG
682                                        printk
683                                            (KERN_DEBUG "i2c-proc.o: found normal isa entry for adapter %d, "
684                                             "addr %04x\n", adapter_id,
685                                             addr);
686#endif
687                                        found = 1;
688                                }
689                        }
690                        for (i = 0;
691                             !found
692                             && (address_data->normal_isa_range[i] !=
693                                 SENSORS_ISA_END); i += 3) {
694                                if ((addr >=
695                                     address_data->normal_isa_range[i])
696                                    && (addr <=
697                                        address_data->normal_isa_range[i + 1])
698                                    &&
699                                    ((addr -
700                                      address_data->normal_isa_range[i]) %
701                                     address_data->normal_isa_range[i + 2] ==
702                                     0)) {
703#ifdef DEBUG
704                                        printk
705                                            (KERN_DEBUG "i2c-proc.o: found normal isa_range entry for adapter %d, "
706                                             "addr %04x", adapter_id, addr);
707#endif
708                                        found = 1;
709                                }
710                        }
711                } else {
712                        for (i = 0;
713                             !found && (address_data->normal_i2c[i] !=
714                                 SENSORS_I2C_END); i += 1) {
715                                if (addr == address_data->normal_i2c[i]) {
716                                        found = 1;
717#ifdef DEBUG
718                                        printk
719                                            (KERN_DEBUG "i2c-proc.o: found normal i2c entry for adapter %d, "
720                                             "addr %02x", adapter_id, addr);
721#endif
722                                }
723                        }
724                        for (i = 0;
725                             !found
726                             && (address_data->normal_i2c_range[i] !=
727                                 SENSORS_I2C_END); i += 2) {
728                                if ((addr >=
729                                     address_data->normal_i2c_range[i])
730                                    && (addr <=
731                                        address_data->normal_i2c_range[i + 1]))
732                                {
733#ifdef DEBUG
734                                        printk
735                                            (KERN_DEBUG "i2c-proc.o: found normal i2c_range entry for adapter %d, "
736                                             "addr %04x\n", adapter_id, addr);
737#endif
738                                        found = 1;
739                                }
740                        }
741                }
742
743                for (i = 0;
744                     !found && (address_data->probe[i] != SENSORS_I2C_END);
745                     i += 2) {
746                        if (((adapter_id == address_data->probe[i]) ||
747                             ((address_data->
748                               probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa))
749                            && (addr == address_data->probe[i + 1])) {
750#ifdef DEBUG
751                                printk
752                                    (KERN_DEBUG "i2c-proc.o: found probe parameter for adapter %d, "
753                                     "addr %04x\n", adapter_id, addr);
754#endif
755                                found = 1;
756                        }
757                }
758                for (i = 0; !found &&
759                           (address_data->probe_range[i] != SENSORS_I2C_END);
760                     i += 3) {
761                        if (
762                            ((adapter_id == address_data->probe_range[i])
763                             ||
764                             ((address_data->probe_range[i] ==
765                               SENSORS_ANY_I2C_BUS) & !is_isa))
766                            && (addr >= address_data->probe_range[i + 1])
767                            && (addr <= address_data->probe_range[i + 2])) {
768                                found = 1;
769#ifdef DEBUG
770                                printk
771                                    (KERN_DEBUG "i2c-proc.o: found probe_range parameter for adapter %d, "
772                                     "addr %04x\n", adapter_id, addr);
773#endif
774                        }
775                }
776                if (!found)
777                        continue;
778
779                /* OK, so we really should examine this address. First check
780                   whether there is some client here at all! */
781                if (is_isa ||
782                    (i2c_smbus_xfer
783                     (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
784                        if ((err = found_proc(adapter, addr, 0, -1)))
785                                return err;
786        }
787        return 0;
788}
789
790static int __init i2c_proc_init(void)
791{
792        printk(KERN_INFO "i2c-proc.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
793        if (!
794            (i2c_proc_header =
795             register_sysctl_table(i2c_proc, 0))) {
796                printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
797                return -EPERM;
798        }
799        i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;
800        return 0;
801}
802
803static void __exit i2c_proc_exit(void)
804{
805        unregister_sysctl_table(i2c_proc_header);
806}
807
808EXPORT_SYMBOL(i2c_register_entry);
809EXPORT_SYMBOL(i2c_deregister_entry);
810EXPORT_SYMBOL(i2c_proc_real);
811EXPORT_SYMBOL(i2c_sysctl_real);
812EXPORT_SYMBOL(i2c_detect);
813
814MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
815MODULE_DESCRIPTION("i2c-proc driver");
816MODULE_LICENSE("GPL");
817
818module_init(i2c_proc_init);
819module_exit(i2c_proc_exit);
Note: See TracBrowser for help on using the browser.