[PATCH 4/5] add i2c_probe_device and i2c_remove_device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add new i2c_probe_device and i2c_remove_device functions to explicitly
instantiate new i2c clients by adapter, driver id and bus address.

These functions can be used for special-purpose adapters, such as those
on TV tuner cards, where we generally know in advance what devices are
attached.  This is important in cases where the adapter does not support
probing or when probing is potentially dangerous to the connected
devices.

Signed-off-by: Nathan Lutchansky <[email protected]>

 drivers/i2c/i2c-core.c |   71 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c.h    |    6 ++++
 2 files changed, 77 insertions(+)

Index: linux-2.6.13-rc6+gregkh/drivers/i2c/i2c-core.c
===================================================================
--- linux-2.6.13-rc6+gregkh.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.13-rc6+gregkh/drivers/i2c/i2c-core.c
@@ -671,6 +671,75 @@ int i2c_control(struct i2c_client *clien
 }
 
 /* ----------------------------------------------------
+ * direct add/remove functions to avoid probing
+ * ----------------------------------------------------
+ */
+
+int i2c_probe_device(struct i2c_adapter *adapter, int driver_id,
+		     int addr, int kind)
+{
+	struct list_head   *item;
+	struct i2c_driver  *driver = NULL;
+
+	/* There's no way to probe addresses on this adapter... */
+	if (kind < 0 && !i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
+		return -EINVAL;
+
+	down(&core_lists);
+	list_for_each(item,&drivers) {
+		driver = list_entry(item, struct i2c_driver, list);
+		if (driver->id == driver_id)
+			break;
+	}
+	up(&core_lists);
+	if (!item)
+		return -ENOENT;
+
+	/* Already in use? */
+	if (i2c_check_addr(adapter, addr))
+		return -EBUSY;
+
+	/* Make sure there is something at this address, unless forced */
+	if (kind < 0) {
+		if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+				   I2C_SMBUS_QUICK, NULL) < 0)
+			return -ENODEV;
+
+		/* prevent 24RF08 corruption */
+		if ((addr & ~0x0f) == 0x50)
+			i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+				       I2C_SMBUS_QUICK, NULL);
+	}
+
+	return driver->detect_client(adapter, addr, kind);
+}
+
+int i2c_remove_device(struct i2c_adapter *adapter, int driver_id, int addr)
+{
+	struct list_head  *item, *_n;
+	struct i2c_client *client;
+	int res = 0;
+
+	down(&core_lists);
+
+	list_for_each_safe(item, _n, &adapter->clients) {
+		client = list_entry(item, struct i2c_client, list);
+		if (client->addr != addr || client->driver->id != driver_id)
+			continue;
+		if ((res=client->driver->detach_client(client)))
+			dev_err(&adapter->dev, "detach_client failed for "
+				"client [%s] at address 0x%02x\n",
+				client->name, client->addr);
+		goto out_unlock;
+	}
+	res = -ENOENT;
+
+ out_unlock:
+	up(&core_lists);
+	return res;
+}
+
+/* ----------------------------------------------------
  * the i2c address scanning function
  * Will not work for 10-bit addresses!
  * ----------------------------------------------------
@@ -1230,6 +1299,8 @@ EXPORT_SYMBOL(i2c_control);
 EXPORT_SYMBOL(i2c_transfer);
 EXPORT_SYMBOL(i2c_get_adapter);
 EXPORT_SYMBOL(i2c_put_adapter);
+EXPORT_SYMBOL(i2c_probe_device);
+EXPORT_SYMBOL(i2c_remove_device);
 EXPORT_SYMBOL(i2c_probe);
 
 EXPORT_SYMBOL(i2c_smbus_xfer);
Index: linux-2.6.13-rc6+gregkh/include/linux/i2c.h
===================================================================
--- linux-2.6.13-rc6+gregkh.orig/include/linux/i2c.h
+++ linux-2.6.13-rc6+gregkh/include/linux/i2c.h
@@ -359,6 +359,12 @@ extern void i2c_clients_command(struct i
    you can cheat by simply not registering. Not recommended, of course! */
 extern int i2c_check_addr (struct i2c_adapter *adapter, int addr);
 
+/* Direct add/remove functions to create or remove clients by address. */
+extern int i2c_probe_device(struct i2c_adapter *adapter, int driver_id,
+			    int addr, int kind);
+extern int i2c_remove_device(struct i2c_adapter *adapter, int driver_id,
+			     int addr);
+
 /* Detect function. It iterates over all possible addresses itself.
  * It will only call found_proc if some client is connected at the
  * specific address (unless a 'force' matched);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux