Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | i2c-sensor-detect.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 | #include <linux/module.h> | |
23 | #include <linux/kernel.h> | |
24 | #include <linux/i2c.h> | |
25 | #include <linux/i2c-sensor.h> | |
26 | ||
27 | static unsigned short empty[] = {I2C_CLIENT_END}; | |
28 | static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END}; | |
29 | ||
30 | /* Very inefficient for ISA detects, and won't work for 10-bit addresses! */ | |
31 | int i2c_detect(struct i2c_adapter *adapter, | |
32 | struct i2c_address_data *address_data, | |
33 | int (*found_proc) (struct i2c_adapter *, int, int)) | |
34 | { | |
35 | int addr, i, found, j, err; | |
36 | struct i2c_force_data *this_force; | |
37 | int is_isa = i2c_is_isa_adapter(adapter); | |
38 | int adapter_id = | |
39 | is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter); | |
40 | unsigned short *normal_i2c; | |
41 | unsigned int *normal_isa; | |
42 | unsigned short *probe; | |
43 | unsigned short *ignore; | |
44 | ||
45 | /* Forget it if we can't probe using SMBUS_QUICK */ | |
46 | if ((!is_isa) && | |
47 | !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) | |
48 | return -1; | |
49 | ||
50 | /* Use default "empty" list if the adapter doesn't specify any */ | |
51 | normal_i2c = probe = ignore = empty; | |
52 | normal_isa = empty_isa; | |
53 | if (address_data->normal_i2c) | |
54 | normal_i2c = address_data->normal_i2c; | |
55 | if (address_data->normal_isa) | |
56 | normal_isa = address_data->normal_isa; | |
57 | if (address_data->probe) | |
58 | probe = address_data->probe; | |
59 | if (address_data->ignore) | |
60 | ignore = address_data->ignore; | |
61 | ||
62 | for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) { | |
63 | if (!is_isa && i2c_check_addr(adapter, addr)) | |
64 | continue; | |
65 | ||
66 | /* If it is in one of the force entries, we don't do any | |
67 | detection at all */ | |
68 | found = 0; | |
69 | for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) { | |
70 | for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) { | |
71 | if ( ((adapter_id == this_force->force[j]) || | |
72 | ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) && | |
73 | (addr == this_force->force[j + 1]) ) { | |
74 | dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr); | |
75 | if ((err = found_proc(adapter, addr, this_force->kind))) | |
76 | return err; | |
77 | found = 1; | |
78 | } | |
79 | } | |
80 | } | |
81 | if (found) | |
82 | continue; | |
83 | ||
84 | /* If this address is in one of the ignores, we can forget about it | |
85 | right now */ | |
86 | for (i = 0; !found && (ignore[i] != I2C_CLIENT_END); i += 2) { | |
87 | if ( ((adapter_id == ignore[i]) || | |
88 | ((ignore[i] == ANY_I2C_BUS) && | |
89 | !is_isa)) && | |
90 | (addr == ignore[i + 1])) { | |
91 | dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr); | |
92 | found = 1; | |
93 | } | |
94 | } | |
95 | if (found) | |
96 | continue; | |
97 | ||
98 | /* Now, we will do a detection, but only if it is in the normal or | |
99 | probe entries */ | |
100 | if (is_isa) { | |
101 | for (i = 0; !found && (normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) { | |
102 | if (addr == normal_isa[i]) { | |
103 | dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr); | |
104 | found = 1; | |
105 | } | |
106 | } | |
107 | } else { | |
108 | for (i = 0; !found && (normal_i2c[i] != I2C_CLIENT_END); i += 1) { | |
109 | if (addr == normal_i2c[i]) { | |
110 | found = 1; | |
111 | dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x\n", adapter_id, addr); | |
112 | } | |
113 | } | |
114 | } | |
115 | ||
116 | for (i = 0; | |
117 | !found && (probe[i] != I2C_CLIENT_END); | |
118 | i += 2) { | |
119 | if (((adapter_id == probe[i]) || | |
120 | ((probe[i] == ANY_I2C_BUS) && !is_isa)) | |
121 | && (addr == probe[i + 1])) { | |
122 | dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr); | |
123 | found = 1; | |
124 | } | |
125 | } | |
126 | if (!found) | |
127 | continue; | |
128 | ||
129 | /* OK, so we really should examine this address. First check | |
130 | whether there is some client here at all! */ | |
131 | if (is_isa || | |
132 | (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0)) | |
133 | if ((err = found_proc(adapter, addr, -1))) | |
134 | return err; | |
135 | } | |
136 | return 0; | |
137 | } | |
138 | ||
139 | EXPORT_SYMBOL(i2c_detect); | |
140 | ||
141 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " | |
142 | "Rudolf Marek <r.marek@sh.cvut.cz>"); | |
143 | ||
144 | MODULE_DESCRIPTION("i2c-sensor driver"); | |
145 | MODULE_LICENSE("GPL"); |