Chinaunix首页 | 论坛 | 博客
  • 博客访问: 164800
  • 博文数量: 36
  • 博客积分: 830
  • 博客等级: 准尉
  • 技术积分: 409
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-10 16:23
文章分类
文章存档

2013年(1)

2012年(35)

分类: 嵌入式

2012-11-26 17:01:05

欢迎转载和指导,然后再吐槽!!!

 

升级I2C驱动到新的2.6设备模型中

——————————————————————

Ben Dooks

 

介绍

——————————————————————

这个指导概括了怎么样改变目前linux 2.6内核中client驱动的方法从老的到新的绑定方法。

 

Old-style 驱动例子:

——————————————————————————————

 

Struct example_state {

       Struct i2c_client_client;

       ....

};

 

Static struct i2c_driver example_driver;

 

static unsigned short ignore[] = { I2C_CLIENT_END };

static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };

 

I2C_CLIENT_INSMOD;

 

static int example_attach(struct i2c_adapter *adap, int addr, int kind)

{

       struct example_state *state;

       struct device *dev = &adap->dev;  /* 用于 dev_ reports */

       int ret;

 

       state = kzalloc(sizeof(struct example_state), GFP_KERNEL);

       if (state == NULL) {

              dev_err(dev, "failed to create our state\n");

              return -ENOMEM;

       }

 

       example->client.addr    = addr;

       example->client.flags   = 0;

       example->client.adapter = adap;

 

       i2c_set_clientdata(&state->i2c_client, state);

       strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);

 

       ret = i2c_attach_client(&state->i2c_client);

       if (ret < 0) {

              dev_err(dev, "failed to attach client\n");

              kfree(state);

              return ret;

       }

 

       dev = &state->i2c_client.dev;

 

       /* 做剩下的初始化工作. */

 

       dev_info(dev, "example client created\n");

 

       return 0;

}

 

static int __devexit example_detach(struct i2c_client *client)

{

       struct example_state *state = i2c_get_clientdata(client);

 

       i2c_detach_client(client);

       kfree(state);

       return 0;

}

 

static int example_attach_adapter(struct i2c_adapter *adap)

{

       return i2c_probe(adap, &addr_data, example_attach);

}

 

static struct i2c_driver example_driver = {

      .driver            = {

              .owner           = THIS_MODULE,

              .name             = "example",

       },

       .attach_adapter = example_attach_adapter,

       .detach_client  = __devexit_p(example_detach),

       .suspend  = example_suspend,

       .resume          = example_resume,

};

 

更新client

————————————————————————————————————

 

New style绑定模型会核对所支持设备的一个表,他们代码提供用于注册总线的相关地址。就是说驱动 .attach_adapter .detach_adapter方法可以被干掉了,连同addr_data,像下面一样:(注意前面的“- 表示被干掉了)

- static struct i2c_driver example_driver;

 

- static unsigned short ignore[] = { I2C_CLIENT_END };

- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };

 

- I2C_CLIENT_INSMOD;

 

- static int example_attach_adapter(struct i2c_adapter *adap)

- {

-     return i2c_probe(adap, &addr_data, example_attach);

- }

 

 static struct i2c_driver example_driver = {

-      .attach_adapter = example_attach_adapter,

-      .detach_client  = __devexit_p(example_detach),

 }

 

i2c_driver中加入Proberemove方法,正如:

 

static struct i2c_driver example_driver = {

+     .probe            = example_probe,

+     .remove          = __devexit_p(example_remove),

 }

 

改变example_attach方法接收新的参数,参数包含了i2c_client,将会与下面的一起工作:

- static int example_attach(struct i2c_adapter *adap, int addr, int kind)

+ static int example_probe(struct i2c_client *client,

+                      const struct i2c_device_id *id

 

example_probe的名字改成example_probe使得它和i2c_driver的入口名字进行匹配。Probe程序的剩下部分也得改了,因为这个时候i2c_client已经设置可以使用了。

 

probe函数调用前,必须的client域已经建立设置了,所以下面的client设置可以不用了。

 

-      example->client.addr    = addr;

-      example->client.flags   = 0;

-      example->client.adapter = adap;

-

-      strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);

 

现在i2c_set_clientdata变成了:

-      i2c_set_clientdata(&state->client, state);

+     i2c_set_clientdata(client, state);

对于i2c_attach_client函数的调用也不需要了,如果probe程序成功结束的话,驱动就不会自动附上通过核心。改变probe程序如下:

 

-      ret = i2c_attach_client(&state->i2c_client);

-      if (ret < 0) {

-             dev_err(dev, "failed to attach client\n");

-             kfree(state);

-             return ret;

-      }

 

struct example_state中的struct i2c_client去掉,因为我们在example_probe中提供了i2c_client,当我们需要它的时候,我们就可以取它的一个指针。

struct example_state {

-      struct i2c_client      client;

+     struct i2c_client      *client;

 

新的I2c client如下:

-      struct device *dev = &adap->dev;  /* 用于 dev_ reports */

+    struct device *dev = &i2c_client->dev;  /* 用于 dev_ reports */

 

我们client附上之后,就可以移除这个改变了,因为驱动不再需要在核心中注册一个client 结构体

 

-      dev = &state->i2c_client.dev;

 

probe程序中,确定新的state里面包含了client

 

static int example_probe(struct i2c_client *i2c_client,

                      const struct i2c_device_id *id)

{

       struct example_state *state;

      struct device *dev = &i2c_client->dev;

       int ret;

 

       state = kzalloc(sizeof(struct example_state), GFP_KERNEL);

       if (state == NULL) {

              dev_err(dev, "failed to create our state\n");

              return -ENOMEM;

       }

 

+     state->client = i2c_client;

 

更新detach方法,通过改变_remove 然后删除i2c_detach_client 调用。有可能你也会移除ret变量 ,因为它对于很多核心的函数不再需要。

- static int __devexit example_detach(struct i2c_client *client)

+ static int __devexit example_remove(struct i2c_client *client)

{

       struct example_state *state = i2c_get_clientdata(client);

 

-      i2c_detach_client(client);

 

最后确定我们有正确的ID表用于i2c-core 和其他的一些工具。

 

+ struct i2c_device_id example_idtable[] = {

+       { "example", 0 },

+       { }

+};

+

+MODULE_DEVICE_TABLE(i2c, example_idtable);

 

static struct i2c_driver example_driver = {

      .driver            = {

              .owner           = THIS_MODULE,

              .name             = "example",

       },

+     .id_table  = example_ids,

 

我们的驱动应该像下面这个一样:

struct example_state {

       struct i2c_client      *client;

       ....

};

 

static int example_probe(struct i2c_client *client,

                         const struct i2c_device_id *id)

{

       struct example_state *state;

       struct device *dev = &client->dev;

 

       state = kzalloc(sizeof(struct example_state), GFP_KERNEL);

       if (state == NULL) {

              dev_err(dev, "failed to create our state\n");

              return -ENOMEM;

       }

 

       state->client = client;

       i2c_set_clientdata(client, state);

 

       /* rest of the initialisation goes here. */

 

       dev_info(dev, "example client created\n");

 

       return 0;

}

 

static int __devexit example_remove(struct i2c_client *client)

{

       struct example_state *state = i2c_get_clientdata(client);

 

       kfree(state);

       return 0;

}

 

static struct i2c_device_id example_idtable[] = {

       { "example", 0 },

       { }

};

 

MODULE_DEVICE_TABLE(i2c, example_idtable);

 

static struct i2c_driver example_driver = {

      .driver            = {

              .owner           = THIS_MODULE,

              .name             = "example",

       },

       .id_table  = example_idtable,

       .probe            = example_probe,

       .remove          = __devexit_p(example_remove),

       .suspend  = example_suspend,

       .resume          = example_resume,

};

 

 

阅读(1712) | 评论(0) | 转发(0) |
0

上一篇:IIC协议

下一篇:怎么写I2c和SMBus设备驱动

给主人留下些什么吧!~~