Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 7182
b: refs/heads/master
c: a89ba0b
h: refs/heads/master
v: v3
  • Loading branch information
Jean Delvare authored and Greg Kroah-Hartman committed Sep 5, 2005
1 parent 5cf781d commit 8092674
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 80 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3b6c0634cc989f0735a1541ccf9288947685cab5
refs/heads/master: a89ba0bc02e82920a0f4137aa5d655ac0366cc28
7 changes: 4 additions & 3 deletions trunk/Documentation/i2c/writing-clients
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,10 @@ Below, some things are only needed if this is a `sensors' driver. Those
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
markers.

This function should only return an error (any value != 0) if there is
some reason why no more detection should be done anymore. If the
detection just fails for this address, return 0.
Returning an error different from -ENODEV in a detect function will cause
the detection to stop: other addresses and adapters won't be scanned.
This should only be done on fatal or internal errors, such as a memory
shortage or i2c_attach_client failing.

For now, you can ignore the `flags' parameter. It is there for future use.

Expand Down
165 changes: 89 additions & 76 deletions trunk/drivers/i2c/i2c-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,107 +662,120 @@ int i2c_control(struct i2c_client *client,
* Will not work for 10-bit addresses!
* ----------------------------------------------------
*/
/* Return: kind (>= 0) if force found, -1 if not found */
static inline int i2c_probe_forces(struct i2c_adapter *adapter, int addr,
unsigned short **forces)
static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
int (*found_proc) (struct i2c_adapter *, int, int))
{
unsigned short kind;
int j, adap_id = i2c_adapter_id(adapter);

for (kind = 0; forces[kind]; kind++) {
for (j = 0; forces[kind][j] != I2C_CLIENT_END; j += 2) {
if ((forces[kind][j] == adap_id ||
forces[kind][j] == ANY_I2C_BUS)
&& forces[kind][j + 1] == addr) {
dev_dbg(&adapter->dev, "found force parameter, "
"addr 0x%02x, kind %u\n", addr, kind);
return kind;
}
}
int err;

/* Make sure the address is valid */
if (addr < 0x03 || addr > 0x77) {
dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
addr);
return -EINVAL;
}

return -1;
/* Skip if already in use */
if (i2c_check_addr(adapter, addr))
return 0;

/* Make sure there is something at this address, unless forced */
if (kind < 0
&& i2c_smbus_xfer(adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0)
return 0;

/* Finally call the custom detection function */
err = found_proc(adapter, addr, kind);

/* -ENODEV can be returned if there is a chip at the given address
but it isn't supported by this chip driver. We catch it here as
this isn't an error. */
return (err == -ENODEV) ? 0 : err;
}

int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
int (*found_proc) (struct i2c_adapter *, int, int))
{
int addr,i,found,err;
int i, err;
int adap_id = i2c_adapter_id(adapter);

/* Forget it if we can't probe using SMBUS_QUICK */
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
return -1;

for (addr = 0x00; addr <= 0x7f; addr++) {

/* Skip if already in use */
if (i2c_check_addr(adapter,addr))
continue;

/* If it is in one of the force entries, we don't do any detection
at all */
found = 0;

if (address_data->forces) {
int kind = i2c_probe_forces(adapter, addr,
address_data->forces);
if (kind >= 0) { /* force found */
if ((err = found_proc(adapter, addr, kind)))
return err;
continue;
}
}

/* If this address is in one of the ignores, we can forget about
it right now */
for (i = 0;
!found && (address_data->ignore[i] != I2C_CLIENT_END);
i += 2) {
if (((adap_id == address_data->ignore[i]) ||
((address_data->ignore[i] == ANY_I2C_BUS))) &&
(addr == address_data->ignore[i+1])) {
dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
"addr %04x\n", adap_id ,addr);
found = 1;
/* Force entries are done first, and are not affected by ignore
entries */
if (address_data->forces) {
unsigned short **forces = address_data->forces;
int kind;

for (kind = 0; forces[kind]; kind++) {
for (i = 0; forces[kind][i] != I2C_CLIENT_END;
i += 2) {
if (forces[kind][i] == adap_id
|| forces[kind][i] == ANY_I2C_BUS) {
dev_dbg(&adapter->dev, "found force "
"parameter for adapter %d, "
"addr 0x%02x, kind %d\n",
adap_id, forces[kind][i + 1],
kind);
err = i2c_probe_address(adapter,
forces[kind][i + 1],
kind, found_proc);
if (err)
return err;
}
}
}
if (found)
continue;
}

/* Now, we will do a detection, but only if it is in the normal or
probe entries */
for (i = 0;
!found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
i += 1) {
if (addr == address_data->normal_i2c[i]) {
found = 1;
dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
"addr %02x\n", adap_id, addr);
}
/* Probe entries are done second, and are not affected by ignore
entries either */
for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
if (address_data->probe[i] == adap_id
|| address_data->probe[i] == ANY_I2C_BUS) {
dev_dbg(&adapter->dev, "found probe parameter for "
"adapter %d, addr 0x%02x\n", adap_id,
address_data->probe[i + 1]);
err = i2c_probe_address(adapter,
address_data->probe[i + 1],
-1, found_proc);
if (err)
return err;
}
}

for (i = 0;
!found && (address_data->probe[i] != I2C_CLIENT_END);
i += 2) {
if (((adap_id == address_data->probe[i]) ||
((address_data->probe[i] == ANY_I2C_BUS))) &&
(addr == address_data->probe[i+1])) {
found = 1;
dev_dbg(&adapter->dev, "found probe parameter for adapter %d, "
"addr %04x\n", adap_id,addr);
/* Normal entries are done last, unless shadowed by an ignore entry */
for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
int j, ignore;

ignore = 0;
for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
j += 2) {
if ((address_data->ignore[j] == adap_id ||
address_data->ignore[j] == ANY_I2C_BUS)
&& address_data->ignore[j + 1]
== address_data->normal_i2c[i]) {
dev_dbg(&adapter->dev, "found ignore "
"parameter for adapter %d, "
"addr 0x%02x\n", adap_id,
address_data->ignore[j + 1]);
}
ignore = 1;
break;
}
if (!found)
if (ignore)
continue;

/* OK, so we really should examine this address. First check
whether there is some client here at all! */
if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
if ((err = found_proc(adapter,addr,-1)))
return err;
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id,
address_data->normal_i2c[i]);
err = i2c_probe_address(adapter, address_data->normal_i2c[i],
-1, found_proc);
if (err)
return err;
}

return 0;
}

Expand Down

0 comments on commit 8092674

Please sign in to comment.