i2c_driver结构体

/**
 * 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值