当系统开机、I2C总线驱动装入完成后,就可以装入设备驱动了。首先装入如下结构:
static struct i2c_driver driver =
{
.name = "i2c TV tuner driver",
.id = I2C_DRIVERID_TUNER,
.flags = I2C_DF_NOTIFY,
.attach_adapter = tuner_probe,
.detach_client = tuner_detach,
.command = tuner_command,
};
i2c_add_driver(&driver);
|
这个i2c_driver一旦装入完成,其中的attach_adapter函数就会被调用。在其中可以遍历系统中的每个i2c总线驱动,探测想要访问的设备:
static int tuner_probe(struct i2c_adapter *adap)
{
return i2c_probe(adap, &addr_data, tuner_attach);
}
|
注意探测可能会找到多个设备,因而不仅一个I2C总线可以挂多个不同类型的设备,一个设备驱动也可以同时为挂在多个不同I2C总线上的设备服务。
每当设备驱动探测到了一个它能支持的设备,它就创建一个struct i2c_client来标识这个设备:
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &driver;
/* Tell the I2C layer a new client has arrived */
err = i2c_attach_client(new_client);
if (err)
goto error;
|
可见,一个i2c_client代表着位于adapter总线上,地址为address,使用driver来驱动的一个设备。它将总线驱动与设备驱动,以及设备地址绑定在了一起。一个i2c_client就代表着一个I2C设备。
当得到I2C设备后,就可以直接对此设备进行读写:
/*
* The master routines are the ones normally used to transmit data to devices
* on a bus (or read from them). Apart from two basic transfer functions to
* transmit one message at a time, a more complex version can be used to
* transmit an arbitrary number of messages without interruption.
*/
extern int i2c_master_send(struct i2c_client *,const char* ,int);
extern int i2c_master_recv(struct i2c_client *,char* ,int);
|
与通常意义上的读写函数一样,这两个函数对i2c_client指针指定的设备,读写int个char。返回值为读写的字节数。对于我们现有的SLIC的驱动,只要将最后要往总线上进行读写的数据引出传输到这两个函数中,移植工作就算完成了,我们将得到一个Linux版的I2C设备驱动。
--
原文链接: http://www.gnome-cn.org/resources/blog/lonestar/linuxdei2cqudongjiagou
|