| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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"); |