Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: i2c-i801: SMBus patch for Intel DH89xxCC DeviceIDs i2c: Drop i2c_adapter.id i2c: Deprecate i2c_driver.attach_adapter and .detach_adapter i2c-dev: Use standard bus notification mechanism i2c: Export i2c_for_each_dev i2c: Get rid of <linux/i2c-id.h> i2c: Minor fixes to upgrading-clients document i2c: make i2c_get_adapter prototype clearer i2c: Fix typo in instantiating-devices document i2c-boardinfo: Fix typo in comment
This commit is contained in:
commit
444699c850
|
@ -585,16 +585,6 @@ Who: NeilBrown <neilb@suse.de>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: i2c_adapter.id
|
||||
When: June 2011
|
||||
Why: This field is deprecated. I2C device drivers shouldn't change their
|
||||
behavior based on the underlying I2C adapter. Instead, the I2C
|
||||
adapter driver should instantiate the I2C devices and provide the
|
||||
needed platform-specific information.
|
||||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: cancel_rearming_delayed_work[queue]()
|
||||
When: 2.6.39
|
||||
|
||||
|
@ -645,3 +635,12 @@ Who: Florian Westphal <fw@strlen.de>
|
|||
Files: include/linux/netfilter_ipv4/ipt_addrtype.h
|
||||
|
||||
----------------------------
|
||||
|
||||
What: i2c_driver.attach_adapter
|
||||
i2c_driver.detach_adapter
|
||||
When: September 2011
|
||||
Why: These legacy callbacks should no longer be used as i2c-core offers
|
||||
a variety of preferable alternative ways to instantiate I2C devices.
|
||||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
----------------------------
|
||||
|
|
|
@ -16,8 +16,9 @@ Supported adapters:
|
|||
* Intel EP80579 (Tolapai)
|
||||
* Intel 82801JI (ICH10)
|
||||
* Intel 5/3400 Series (PCH)
|
||||
* Intel Cougar Point (PCH)
|
||||
* Intel 6 Series (PCH)
|
||||
* Intel Patsburg (PCH)
|
||||
* Intel DH89xxCC (PCH)
|
||||
Datasheets: Publicly available at the Intel website
|
||||
|
||||
On Intel Patsburg and later chipsets, both the normal host SMBus controller
|
||||
|
|
|
@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
|
|||
(...)
|
||||
i2c_adap = i2c_get_adapter(2);
|
||||
memset(&i2c_info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
|
||||
strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
|
||||
isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
|
||||
normal_i2c, NULL);
|
||||
i2c_put_adapter(i2c_adap);
|
||||
|
|
|
@ -61,7 +61,7 @@ static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit example_detach(struct i2c_client *client)
|
||||
static int example_detach(struct i2c_client *client)
|
||||
{
|
||||
struct example_state *state = i2c_get_clientdata(client);
|
||||
|
||||
|
@ -81,7 +81,7 @@ static struct i2c_driver example_driver = {
|
|||
.name = "example",
|
||||
},
|
||||
.attach_adapter = example_attach_adapter,
|
||||
.detach_client = __devexit_p(example_detach),
|
||||
.detach_client = example_detach,
|
||||
.suspend = example_suspend,
|
||||
.resume = example_resume,
|
||||
};
|
||||
|
@ -93,7 +93,7 @@ Updating the client
|
|||
The new style binding model will check against a list of supported
|
||||
devices and their associated address supplied by the code registering
|
||||
the busses. This means that the driver .attach_adapter and
|
||||
.detach_adapter methods can be removed, along with the addr_data,
|
||||
.detach_client methods can be removed, along with the addr_data,
|
||||
as follows:
|
||||
|
||||
- static struct i2c_driver example_driver;
|
||||
|
@ -110,14 +110,14 @@ as follows:
|
|||
|
||||
static struct i2c_driver example_driver = {
|
||||
- .attach_adapter = example_attach_adapter,
|
||||
- .detach_client = __devexit_p(example_detach),
|
||||
- .detach_client = example_detach,
|
||||
}
|
||||
|
||||
Add the probe and remove methods to the i2c_driver, as so:
|
||||
|
||||
static struct i2c_driver example_driver = {
|
||||
+ .probe = example_probe,
|
||||
+ .remove = __devexit_p(example_remove),
|
||||
+ .remove = example_remove,
|
||||
}
|
||||
|
||||
Change the example_attach method to accept the new parameters
|
||||
|
@ -199,8 +199,8 @@ to delete the i2c_detach_client call. It is possible that you
|
|||
can also remove the ret variable as it is not not needed for
|
||||
any of the core functions.
|
||||
|
||||
- static int __devexit example_detach(struct i2c_client *client)
|
||||
+ static int __devexit example_remove(struct i2c_client *client)
|
||||
- static int example_detach(struct i2c_client *client)
|
||||
+ static int example_remove(struct i2c_client *client)
|
||||
{
|
||||
struct example_state *state = i2c_get_clientdata(client);
|
||||
|
||||
|
@ -253,7 +253,7 @@ static int example_probe(struct i2c_client *client,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit example_remove(struct i2c_client *client)
|
||||
static int example_remove(struct i2c_client *client)
|
||||
{
|
||||
struct example_state *state = i2c_get_clientdata(client);
|
||||
|
||||
|
@ -275,7 +275,7 @@ static struct i2c_driver example_driver = {
|
|||
},
|
||||
.id_table = example_idtable,
|
||||
.probe = example_probe,
|
||||
.remove = __devexit_p(example_remove),
|
||||
.remove = example_remove,
|
||||
.suspend = example_suspend,
|
||||
.resume = example_resume,
|
||||
};
|
||||
|
|
|
@ -130,7 +130,7 @@ Card number: 4
|
|||
|
||||
Note: No module for the mse3000 is available yet
|
||||
Note: No module for the vpx3224 is available yet
|
||||
Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h)
|
||||
Note: use encoder=X or decoder=X for non-default i2c chips
|
||||
|
||||
===========================
|
||||
|
||||
|
|
|
@ -10,3 +10,4 @@ obj-$(CONFIG_I2C_MUX) += i2c-mux.o
|
|||
obj-y += algos/ busses/ muxes/
|
||||
|
||||
ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
|
||||
CFLAGS_i2c-core.o := -Wno-deprecated-declarations
|
||||
|
|
|
@ -98,8 +98,9 @@ config I2C_I801
|
|||
EP80579 (Tolapai)
|
||||
ICH10
|
||||
5/3400 Series (PCH)
|
||||
Cougar Point (PCH)
|
||||
6 Series (PCH)
|
||||
Patsburg (PCH)
|
||||
DH89xxCC (PCH)
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-i801.
|
||||
|
|
|
@ -44,11 +44,12 @@
|
|||
ICH10 0x3a30 32 hard yes yes yes
|
||||
ICH10 0x3a60 32 hard yes yes yes
|
||||
5/3400 Series (PCH) 0x3b30 32 hard yes yes yes
|
||||
Cougar Point (PCH) 0x1c22 32 hard yes yes yes
|
||||
6 Series (PCH) 0x1c22 32 hard yes yes yes
|
||||
Patsburg (PCH) 0x1d22 32 hard yes yes yes
|
||||
Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes
|
||||
Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes
|
||||
Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes
|
||||
DH89xxCC (PCH) 0x2330 32 hard yes yes yes
|
||||
|
||||
Features supported by this driver:
|
||||
Software PEC no
|
||||
|
@ -621,6 +622,7 @@ static const struct pci_device_id i801_ids[] = {
|
|||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* i2c-boardinfo.h - collect pre-declarations of I2C devices
|
||||
* i2c-boardinfo.c - collect pre-declarations of I2C devices
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -797,6 +797,9 @@ static int i2c_do_add_adapter(struct i2c_driver *driver,
|
|||
|
||||
/* Let legacy drivers scan this bus for matching devices */
|
||||
if (driver->attach_adapter) {
|
||||
dev_warn(&adap->dev, "attach_adapter method is deprecated\n");
|
||||
dev_warn(&adap->dev, "Please use another way to instantiate "
|
||||
"your i2c_client\n");
|
||||
/* We ignore the return code; if it fails, too bad */
|
||||
driver->attach_adapter(adap);
|
||||
}
|
||||
|
@ -981,6 +984,7 @@ static int i2c_do_del_adapter(struct i2c_driver *driver,
|
|||
|
||||
if (!driver->detach_adapter)
|
||||
return 0;
|
||||
dev_warn(&adapter->dev, "detach_adapter method is deprecated\n");
|
||||
res = driver->detach_adapter(adapter);
|
||||
if (res)
|
||||
dev_err(&adapter->dev, "detach_adapter failed (%d) "
|
||||
|
@ -1091,6 +1095,18 @@ EXPORT_SYMBOL(i2c_del_adapter);
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
|
||||
{
|
||||
int res;
|
||||
|
||||
mutex_lock(&core_lock);
|
||||
res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
|
||||
mutex_unlock(&core_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_for_each_dev);
|
||||
|
||||
static int __process_new_driver(struct device *dev, void *data)
|
||||
{
|
||||
if (dev->type != &i2c_adapter_type)
|
||||
|
@ -1134,9 +1150,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
|
|||
|
||||
INIT_LIST_HEAD(&driver->clients);
|
||||
/* Walk the adapters that are already present */
|
||||
mutex_lock(&core_lock);
|
||||
bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
|
||||
mutex_unlock(&core_lock);
|
||||
i2c_for_each_dev(driver, __process_new_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1156,9 +1170,7 @@ static int __process_removed_driver(struct device *dev, void *data)
|
|||
*/
|
||||
void i2c_del_driver(struct i2c_driver *driver)
|
||||
{
|
||||
mutex_lock(&core_lock);
|
||||
bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);
|
||||
mutex_unlock(&core_lock);
|
||||
i2c_for_each_dev(driver, __process_removed_driver);
|
||||
|
||||
driver_unregister(&driver->driver);
|
||||
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
|
||||
|
@ -1581,12 +1593,12 @@ i2c_new_probed_device(struct i2c_adapter *adap,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_new_probed_device);
|
||||
|
||||
struct i2c_adapter *i2c_get_adapter(int id)
|
||||
struct i2c_adapter *i2c_get_adapter(int nr)
|
||||
{
|
||||
struct i2c_adapter *adapter;
|
||||
|
||||
mutex_lock(&core_lock);
|
||||
adapter = idr_find(&i2c_adapter_idr, id);
|
||||
adapter = idr_find(&i2c_adapter_idr, nr);
|
||||
if (adapter && !try_module_get(adapter->owner))
|
||||
adapter = NULL;
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -37,16 +39,13 @@
|
|||
#include <linux/jiffies.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static struct i2c_driver i2cdev_driver;
|
||||
|
||||
/*
|
||||
* An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
|
||||
* slave (i2c_client) with which messages will be exchanged. It's coupled
|
||||
* with a character special file which is accessed by user mode drivers.
|
||||
*
|
||||
* The list of i2c_dev structures is parallel to the i2c_adapter lists
|
||||
* maintained by the driver model, and is updated using notifications
|
||||
* delivered to the i2cdev_driver.
|
||||
* maintained by the driver model, and is updated using bus notifications.
|
||||
*/
|
||||
struct i2c_dev {
|
||||
struct list_head list;
|
||||
|
@ -491,7 +490,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
|
|||
return -ENOMEM;
|
||||
}
|
||||
snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
|
||||
client->driver = &i2cdev_driver;
|
||||
|
||||
client->adapter = adap;
|
||||
file->private_data = client;
|
||||
|
@ -522,19 +520,18 @@ static const struct file_operations i2cdev_fops = {
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The legacy "i2cdev_driver" is used primarily to get notifications when
|
||||
* I2C adapters are added or removed, so that each one gets an i2c_dev
|
||||
* and is thus made available to userspace driver code.
|
||||
*/
|
||||
|
||||
static struct class *i2c_dev_class;
|
||||
|
||||
static int i2cdev_attach_adapter(struct i2c_adapter *adap)
|
||||
static int i2cdev_attach_adapter(struct device *dev, void *dummy)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_dev *i2c_dev;
|
||||
int res;
|
||||
|
||||
if (dev->type != &i2c_adapter_type)
|
||||
return 0;
|
||||
adap = to_i2c_adapter(dev);
|
||||
|
||||
i2c_dev = get_free_i2c_dev(adap);
|
||||
if (IS_ERR(i2c_dev))
|
||||
return PTR_ERR(i2c_dev);
|
||||
|
@ -561,10 +558,15 @@ error:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int i2cdev_detach_adapter(struct i2c_adapter *adap)
|
||||
static int i2cdev_detach_adapter(struct device *dev, void *dummy)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_dev *i2c_dev;
|
||||
|
||||
if (dev->type != &i2c_adapter_type)
|
||||
return 0;
|
||||
adap = to_i2c_adapter(dev);
|
||||
|
||||
i2c_dev = i2c_dev_get_by_minor(adap->nr);
|
||||
if (!i2c_dev) /* attach_adapter must have failed */
|
||||
return 0;
|
||||
|
@ -577,12 +579,23 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver i2cdev_driver = {
|
||||
.driver = {
|
||||
.name = "dev_driver",
|
||||
},
|
||||
.attach_adapter = i2cdev_attach_adapter,
|
||||
.detach_adapter = i2cdev_detach_adapter,
|
||||
int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
switch (action) {
|
||||
case BUS_NOTIFY_ADD_DEVICE:
|
||||
return i2cdev_attach_adapter(dev, NULL);
|
||||
case BUS_NOTIFY_DEL_DEVICE:
|
||||
return i2cdev_detach_adapter(dev, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block i2cdev_notifier = {
|
||||
.notifier_call = i2cdev_notifier_call,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -607,10 +620,14 @@ static int __init i2c_dev_init(void)
|
|||
goto out_unreg_chrdev;
|
||||
}
|
||||
|
||||
res = i2c_add_driver(&i2cdev_driver);
|
||||
/* Keep track of adapters which will be added or removed later */
|
||||
res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
|
||||
if (res)
|
||||
goto out_unreg_class;
|
||||
|
||||
/* Bind to already existing adapters right away */
|
||||
i2c_for_each_dev(NULL, i2cdev_attach_adapter);
|
||||
|
||||
return 0;
|
||||
|
||||
out_unreg_class:
|
||||
|
@ -624,7 +641,8 @@ out:
|
|||
|
||||
static void __exit i2c_dev_exit(void)
|
||||
{
|
||||
i2c_del_driver(&i2cdev_driver);
|
||||
bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
|
||||
i2c_for_each_dev(NULL, i2cdev_detach_adapter);
|
||||
class_destroy(i2c_dev_class);
|
||||
unregister_chrdev(I2C_MAJOR, "i2c");
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* ------------------------------------------------------------------------- */
|
||||
/* */
|
||||
/* i2c-id.h - identifier values for i2c drivers and adapters */
|
||||
/* */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-1999 Simon G. Vogl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LINUX_I2C_ID_H
|
||||
#define LINUX_I2C_ID_H
|
||||
|
||||
/* Please note that I2C driver IDs are optional. They are only needed if a
|
||||
legacy chip driver needs to identify a bus or a bus driver needs to
|
||||
identify a legacy client. If you don't need them, just don't set them. */
|
||||
|
||||
/*
|
||||
* ---- Adapter types ----------------------------------------------------
|
||||
*/
|
||||
|
||||
/* --- Bit algorithm adapters */
|
||||
#define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */
|
||||
|
||||
#endif /* LINUX_I2C_ID_H */
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/types.h>
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/device.h> /* for struct device */
|
||||
#include <linux/sched.h> /* for completion */
|
||||
|
@ -105,8 +104,8 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
|
|||
/**
|
||||
* struct i2c_driver - represent an I2C device driver
|
||||
* @class: What kind of i2c device we instantiate (for detect)
|
||||
* @attach_adapter: Callback for bus addition (for legacy drivers)
|
||||
* @detach_adapter: Callback for bus removal (for legacy drivers)
|
||||
* @attach_adapter: Callback for bus addition (deprecated)
|
||||
* @detach_adapter: Callback for bus removal (deprecated)
|
||||
* @probe: Callback for device binding
|
||||
* @remove: Callback for device unbinding
|
||||
* @shutdown: Callback for device shutdown
|
||||
|
@ -144,11 +143,11 @@ struct i2c_driver {
|
|||
unsigned int class;
|
||||
|
||||
/* Notifies the driver that a new bus has appeared or is about to be
|
||||
* removed. You should avoid using this if you can, it will probably
|
||||
* be removed in a near future.
|
||||
* removed. You should avoid using this, it will be removed in a
|
||||
* near future.
|
||||
*/
|
||||
int (*attach_adapter)(struct i2c_adapter *);
|
||||
int (*detach_adapter)(struct i2c_adapter *);
|
||||
int (*attach_adapter)(struct i2c_adapter *) __deprecated;
|
||||
int (*detach_adapter)(struct i2c_adapter *) __deprecated;
|
||||
|
||||
/* Standard driver model interfaces */
|
||||
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
|
||||
|
@ -354,7 +353,6 @@ struct i2c_algorithm {
|
|||
*/
|
||||
struct i2c_adapter {
|
||||
struct module *owner;
|
||||
unsigned int id __deprecated;
|
||||
unsigned int class; /* classes to allow probing for */
|
||||
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
|
||||
void *algo_data;
|
||||
|
@ -396,6 +394,8 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *));
|
||||
|
||||
/* Adapter locking functions, exported for shared pin cases */
|
||||
void i2c_lock_adapter(struct i2c_adapter *);
|
||||
void i2c_unlock_adapter(struct i2c_adapter *);
|
||||
|
@ -447,7 +447,7 @@ extern void i2c_release_client(struct i2c_client *client);
|
|||
extern void i2c_clients_command(struct i2c_adapter *adap,
|
||||
unsigned int cmd, void *arg);
|
||||
|
||||
extern struct i2c_adapter *i2c_get_adapter(int id);
|
||||
extern struct i2c_adapter *i2c_get_adapter(int nr);
|
||||
extern void i2c_put_adapter(struct i2c_adapter *adap);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue