aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2007-11-15 13:24:01 -0500
committerJean Delvare <khali@hyperion.delvare>2007-11-15 13:24:01 -0500
commit907135aaa0cc120a347222c8f274ecc5ca0db641 (patch)
tree0572c3fc649030ffee737907228a9bfb6094a63a
parent99fee6d7e5748d96884667a4628118f7fc130ea0 (diff)
i2c-dev: "how does it work" comments
This adds some "how does this work" comments to the i2c-dev driver, plus separators between the three main components: - The parallel list of i2c_adapters ("i2c_dev_list"), each of which gets a "struct i2c_dev" and a /dev/i2c-X character special file. - An i2cdev_driver gets adapter add/remove notifications, which are used to maintain that list of adapters. - Special file operations, which let userspace talk either directly to the adapter (for i2c_msg operations) or through cached addressing info using an anonymous i2c_client (never registered anywhere). Plus there's the usual module load/unload record keeping. After making sense of this code, I think that the anonymous i2c_client is pretty shady. But since it's never registered, using this code with a system set up for "new style" I2C drivers is no more complicated than always using the I2C_SLAVE_FORCE ioctl (instead of I2C_SLAVE). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--drivers/i2c/i2c-dev.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 5a15e50748de..7360f9c37256 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -38,6 +38,15 @@
38 38
39static struct i2c_driver i2cdev_driver; 39static struct i2c_driver i2cdev_driver;
40 40
41/*
42 * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
43 * slave (i2c_client) with which messages will be exchanged. It's coupled
44 * with a character special file which is accessed by user mode drivers.
45 *
46 * The list of i2c_dev structures is parallel to the i2c_adapter lists
47 * maintained by the driver model, and is updated using notifications
48 * delivered to the i2cdev_driver.
49 */
41struct i2c_dev { 50struct i2c_dev {
42 struct list_head list; 51 struct list_head list;
43 struct i2c_adapter *adap; 52 struct i2c_adapter *adap;
@@ -103,6 +112,25 @@ static ssize_t show_adapter_name(struct device *dev,
103} 112}
104static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); 113static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
105 114
115/* ------------------------------------------------------------------------- */
116
117/*
118 * After opening an instance of this character special file, a file
119 * descriptor starts out associated only with an i2c_adapter (and bus).
120 *
121 * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg
122 * traffic to any devices on the bus used by that adapter. That's because
123 * the i2c_msg vectors embed all the addressing information they need, and
124 * are submitted directly to an i2c_adapter. However, SMBus-only adapters
125 * don't support that interface.
126 *
127 * To use read()/write() system calls on that file descriptor, or to use
128 * SMBus interfaces (and work with SMBus-only hosts!), you must first issue
129 * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous
130 * (never registered) i2c_client so it holds the addressing information
131 * needed by those system calls and by this SMBus interface.
132 */
133
106static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, 134static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
107 loff_t *offset) 135 loff_t *offset)
108{ 136{
@@ -172,6 +200,16 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
172 switch ( cmd ) { 200 switch ( cmd ) {
173 case I2C_SLAVE: 201 case I2C_SLAVE:
174 case I2C_SLAVE_FORCE: 202 case I2C_SLAVE_FORCE:
203 /* NOTE: devices set up to work with "new style" drivers
204 * can't use I2C_SLAVE, even when the device node is not
205 * bound to a driver. Only I2C_SLAVE_FORCE will work.
206 *
207 * Setting the PEC flag here won't affect kernel drivers,
208 * which will be using the i2c_client node registered with
209 * the driver model core. Likewise, when that client has
210 * the PEC flag already set, the i2c-dev driver won't see
211 * (or use) this setting.
212 */
175 if ((arg > 0x3ff) || 213 if ((arg > 0x3ff) ||
176 (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) 214 (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
177 return -EINVAL; 215 return -EINVAL;
@@ -386,6 +424,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
386 if (!adap) 424 if (!adap)
387 return -ENODEV; 425 return -ENODEV;
388 426
427 /* This creates an anonymous i2c_client, which may later be
428 * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
429 *
430 * This client is ** NEVER REGISTERED ** with the driver model
431 * or I2C core code!! It just holds private copies of addressing
432 * information and maybe a PEC flag.
433 */
389 client = kzalloc(sizeof(*client), GFP_KERNEL); 434 client = kzalloc(sizeof(*client), GFP_KERNEL);
390 if (!client) { 435 if (!client) {
391 i2c_put_adapter(adap); 436 i2c_put_adapter(adap);
@@ -394,7 +439,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
394 snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); 439 snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
395 client->driver = &i2cdev_driver; 440 client->driver = &i2cdev_driver;
396 441
397 /* registered with adapter, passed as client to user */
398 client->adapter = adap; 442 client->adapter = adap;
399 file->private_data = client; 443 file->private_data = client;
400 444
@@ -422,6 +466,14 @@ static const struct file_operations i2cdev_fops = {
422 .release = i2cdev_release, 466 .release = i2cdev_release,
423}; 467};
424 468
469/* ------------------------------------------------------------------------- */
470
471/*
472 * The legacy "i2cdev_driver" is used primarily to get notifications when
473 * I2C adapters are added or removed, so that each one gets an i2c_dev
474 * and is thus made available to userspace driver code.
475 */
476
425static struct class *i2c_dev_class; 477static struct class *i2c_dev_class;
426 478
427static int i2cdev_attach_adapter(struct i2c_adapter *adap) 479static int i2cdev_attach_adapter(struct i2c_adapter *adap)
@@ -486,6 +538,12 @@ static struct i2c_driver i2cdev_driver = {
486 .detach_client = i2cdev_detach_client, 538 .detach_client = i2cdev_detach_client,
487}; 539};
488 540
541/* ------------------------------------------------------------------------- */
542
543/*
544 * module load/unload record keeping
545 */
546
489static int __init i2c_dev_init(void) 547static int __init i2c_dev_init(void)
490{ 548{
491 int res; 549 int res;