/* ------------------------------------------------------------------------- */
-void i2c_adapter_dev_release(struct device *dev)
-{
- struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
- complete(&adap->dev_released);
-}
-
-struct device_driver i2c_adapter_driver = {
- .owner = THIS_MODULE,
- .name = "i2c_adapter",
- .bus = &i2c_bus_type,
-};
-
-/* ------------------------------------------------------------------------- */
-
/* I2C bus adapters -- one roots each I2C or SMBUS segment */
-static void i2c_adapter_class_dev_release(struct class_device *dev)
+void i2c_adapter_dev_release(struct device *dev)
{
- struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev);
- complete(&adap->class_dev_released);
+ struct i2c_adapter *adap = to_i2c_adapter(dev);
+ complete(&adap->dev_released);
}
-static ssize_t i2c_adapter_show_name(struct class_device *cdev, char *buf)
+static ssize_t
+show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct i2c_adapter *adap = class_dev_to_i2c_adapter(cdev);
+ struct i2c_adapter *adap = to_i2c_adapter(dev);
return sprintf(buf, "%s\n", adap->name);
}
-static struct class_device_attribute i2c_adapter_attrs[] = {
- __ATTR(name, S_IRUGO, i2c_adapter_show_name, NULL),
+static struct device_attribute i2c_adapter_attrs[] = {
+ __ATTR(name, S_IRUGO, show_adapter_name, NULL),
{ },
};
struct class i2c_adapter_class = {
.owner = THIS_MODULE,
.name = "i2c-adapter",
- .class_dev_attrs = i2c_adapter_attrs,
- .release = &i2c_adapter_class_dev_release,
+ .dev_attrs = i2c_adapter_attrs,
};
-static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
- return sprintf(buf, "%s\n", adap->name);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-
static void i2c_client_release(struct device *dev)
{
"physical device\n", adap->name);
}
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
- adap->dev.driver = &i2c_adapter_driver;
adap->dev.release = &i2c_adapter_dev_release;
+ adap->dev.class = &i2c_adapter_class;
res = device_register(&adap->dev);
if (res)
goto out_list;
- res = device_create_file(&adap->dev, &dev_attr_name);
- if (res)
- goto out_unregister;
-
- /* Add this adapter to the i2c_adapter class */
- memset(&adap->class_dev, 0x00, sizeof(struct class_device));
- adap->class_dev.dev = &adap->dev;
- adap->class_dev.class = &i2c_adapter_class;
- strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
- res = class_device_register(&adap->class_dev);
- if (res)
- goto out_remove_name;
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
mutex_unlock(&core_lists);
return res;
-out_remove_name:
- device_remove_file(&adap->dev, &dev_attr_name);
-out_unregister:
- init_completion(&adap->dev_released); /* Needed? */
- device_unregister(&adap->dev);
- wait_for_completion(&adap->dev_released);
out_list:
list_del(&adap->list);
idr_remove(&i2c_adapter_idr, adap->nr);
/* clean up the sysfs representation */
init_completion(&adap->dev_released);
- init_completion(&adap->class_dev_released);
- class_device_unregister(&adap->class_dev);
- device_remove_file(&adap->dev, &dev_attr_name);
device_unregister(&adap->dev);
list_del(&adap->list);
/* wait for sysfs to drop all references */
wait_for_completion(&adap->dev_released);
- wait_for_completion(&adap->class_dev_released);
/* free dynamically allocated bus id */
idr_remove(&i2c_adapter_idr, adap->nr);
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
- struct list_head *item;
- struct i2c_adapter *adapter;
int res;
/* add the driver to the list of i2c drivers in the driver core */
/* now look for instances of driver on our adapters */
if (driver->attach_adapter) {
- list_for_each(item,&adapters) {
- adapter = list_entry(item, struct i2c_adapter, list);
+ struct i2c_adapter *adapter;
+
+ list_for_each_entry(adapter, &adapters, list) {
driver->attach_adapter(adapter);
}
}
int retval;
retval = bus_register(&i2c_bus_type);
- if (retval)
- return retval;
- retval = driver_register(&i2c_adapter_driver);
if (retval)
return retval;
return class_register(&i2c_adapter_class);
static void __exit i2c_exit(void)
{
class_unregister(&i2c_adapter_class);
- driver_unregister(&i2c_adapter_driver);
bus_unregister(&i2c_bus_type);
}
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
- "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
- 'R' : 'W', msgs[ret].addr, msgs[ret].len);
+ "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
+ ? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
+ (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
#endif
break;
case I2C_SMBUS_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
- dev_err(&adapter->dev, "Block read not supported "
- "under I2C emulation!\n");
- return -1;
+ msg[1].flags |= I2C_M_RECV_LEN;
+ msg[1].len = 1; /* block length will be added by
+ the underlying bus driver */
} else {
msg[0].len = data->block[0] + 2;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- dev_dbg(&adapter->dev, "Block process call not supported "
- "under I2C emulation!\n");
- return -1;
+ num = 2; /* Another special case */
+ read_write = I2C_SMBUS_READ;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+ dev_err(&adapter->dev, "%s called with invalid "
+ "block proc call size (%d)\n", __FUNCTION__,
+ data->block[0]);
+ return -1;
+ }
+ msg[0].len = data->block[0] + 2;
+ for (i = 1; i < msg[0].len; i++)
+ msgbuf0[i] = data->block[i-1];
+ msg[1].flags |= I2C_M_RECV_LEN;
+ msg[1].len = 1; /* block length will be added by
+ the underlying bus driver */
+ break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
msg[1].len = I2C_SMBUS_BLOCK_MAX;
for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
data->block[i+1] = msgbuf1[i];
break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ for (i = 0; i < msgbuf1[0] + 1; i++)
+ data->block[i] = msgbuf1[i];
+ break;
}
return 0;
}
}
-/* Next four are needed by i2c-isa */
+/* Next three are needed by i2c-isa */
EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
-EXPORT_SYMBOL_GPL(i2c_adapter_driver);
EXPORT_SYMBOL_GPL(i2c_adapter_class);
EXPORT_SYMBOL_GPL(i2c_bus_type);