i2c_driver结构体

来源:互联网 发布:mysql 中文怎么设置 编辑:程序博客网 时间:2024/05/16 00:51
/** * 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) * @probe: Callback for device binding * @remove: Callback for device unbinding * @shutdown: Callback for device shutdown * @suspend: Callback for device suspend * @resume: Callback for device resume * @command: Callback for bus-wide signaling (optional) * @driver: Device driver model driver * @id_table: List of I2C devices supported by this driver * @detect: Callback for device detection * @address_list: The I2C addresses to probe (for detect) * @clients: List of detected clients we created (for i2c-core use only) * * The driver.owner field should be set to the module owner of this driver. * The driver.name field should be set to the name of this driver. * * For automatic device detection, both @detect and @address_data must * be defined. @class should also be set, otherwise only devices forced * with module parameters will be created. The detect function must * fill at least the name field of the i2c_board_info structure it is * handed upon successful detection, and possibly also the flags field. * * If @detect is missing, the driver will still work fine for enumerated * devices. Detected devices simply won't be supported. This is expected * for the many I2C/SMBus devices which can't be detected reliably, and * the ones which can always be enumerated in practice. * * The i2c_client structure which is handed to the @detect callback is * not a real i2c_client. It is initialized just enough so that you can * call i2c_smbus_read_byte_data and friends on it. Don't do anything * else with it. In particular, calling dev_dbg and friends on it is * not allowed. */
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.  */ int (*attach_adapter)(struct i2c_adapter *); int (*detach_adapter)(struct i2c_adapter *); /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); /* driver model interfaces that don't relate to enumeration  */ void (*shutdown)(struct i2c_client *); int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(struct i2c_client *); /* Alert callback, for example for the SMBus alert protocol.  * The format and meaning of the data value depends on the protocol.  * For the SMBus alert protocol, there is a single bit of data passed  * as the alert response's low bit ("event flag").  */ void (*alert)(struct i2c_client *, unsigned int data); /* a ioctl like command that can be used to perform specific functions  * with the device.  */ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); struct device_driver driver;const struct i2c_device_id *id_table; /* Device detection callback for automatic device creation */ int (*detect)(struct i2c_client *, struct i2c_board_info *); const unsigned short *address_list; struct list_head clients;};

static struct i2c_driver pixcir_i2c_ts_driver = {
 .driver = {
  .owner = THIS_MODULE,
  .name = "pixcir_i2c_ts_v3.0",
  .pm = &pixcir_dev_pm_ops,
 },
 .probe  = pixcir_i2c_ts_probe,
 .remove  = __devexit_p(pixcir_i2c_ts_remove),
 .id_table = pixcir_i2c_ts_id,
};

 

驱动程序的主要工作就是定义并初始化一个i2c_driver结构体。i2c_driver的成员参考上面。
 
i2c_driver中的driver成员至少应该初始化它的name成员。

Legacy model的驱动i2c_driver的函数指针至少应该初始化attach_adapter和detach_ client,另外attach_adapter会使用example_attach函数,这个函数主要是将我们的client注册到系统中。这两个函数指针对应的函数实现比较固定。

Standard driver model的驱动需要注册板级信息板级信息必须要有driver的id name还有设备的7位从机地址。驱动中不再需要创建i2c_client结构体,它是由i2c内核创建的。驱动中不需要定义设备的地址,取而代之的是i2c_device_id,用来保存支持的设备类型。这里面保存的设备名将会和板级信息中注册的i2c_board_info的名字进行比较,在i2c_device_id中存在的名字才能依附于本驱动。i2c_driver函数指针成员只需要初始化probe和remove就就够了。其它的函数都是可选的。特别需要注意的是,如果同时初始化两种模式需要用到的i2c_driver的成员,那么会报错,因为i2c内核无法判断是哪种模式的驱动。i2c_driver中的probe、remove、detect任何一个被初始化意味着这是一个Standard driver model模式的驱动,attach_adapter和detach_adapter绝对不可以初始化。

另外,i2c_driver的shutdown、suspend、resume这三个函数指针是否初始化是可选的。这三个函数指针分别对应关机、挂起、唤醒。

如果已经将i2c驱动正确的编译并插入内核,那么内核中提供了一些接口和设备通信:

extern int i2c_master_send(struct i2c_client *client, const char* buf, int len);

extern int i2c_master_recv(struct i2c_client * client,char* buf, int len);

这两个函数都是让client对应的适配器以主机的身份和client->addr地址的设备进行通信,返回值是实际读写的字节数。Linux下的i2c适配器不支持从机模式。

上面的两个函数有个弊端,那就是只能完成单方向的通信,如果通信的过程既有发送又有接收而且接收和发送不能分开,那就需要调用另一个函数:

extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num);

实际上,上面两个函数也是直接调用了i2c_transfer。

i2c_transfer中的参数有三个,第一个是适配器结构体的指针,第二个是消息数组的头指针,第三个是消息的数量。这个函数发送一系列的消息。每个消息可以是读,也可以是写,也可以混合。发送过程是连贯的,在发送中没有停止条件。它的返回值是成功执行的消息数目。

消息的格式定义如下。

struct i2c_msg {
         __u16 addr; // slave address
         __u16 flags;
#define I2C_M_TEN                                0x0010       //10bit地址
#define I2C_M_RD                                  0x0001       //读取数据标志,清零表示写
#define I2C_M_NOSTART                     x4000         //不发送起始位
#define I2C_M_REV_DIR_ADDR        0x2000       // 反转读写标志
#define I2C_M_IGNORE_NAK            x1000         //忽略I2C器件的ack和nack信号
#define I2C_M_NO_RD_ACK               0x0800       //读操作时不去ACK
#define I2C_M_RECV_LEN                   0x0400       //length will be first received byte
         __u16 len; // msg length
         __u8 *buf; // pointer to msg data
};
flags各位的含义已经用宏定义好了。如果连续多条消息的话,除了第一条之外,余下的都不需要发送起始条件。

0 0