Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1045527
  • 博文数量: 277
  • 博客积分: 8313
  • 博客等级: 中将
  • 技术积分: 2976
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-22 11:25
文章分类

全部博文(277)

文章存档

2013年(17)

2012年(66)

2011年(104)

2010年(90)

我的朋友

分类: LINUX

2012-01-10 11:22:20

  1. V4L2中增加I2C设备接口:v4l2_i2c_new_subdev_board接口分析  
  2. struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,  
  3.         struct i2c_adapter *adapter, const char *module_name,  
  4.         struct i2c_board_info *info, const unsigned short *probe_addrs)  
  5. {  
  6.     ........  
  7.     if (module_name)  
  8.         request_module(module_name); //加载I2C驱动模块  
  9.   
  10.     /* Create the i2c client */  
  11.     if (info->addr == 0 && probe_addrs)  
  12.         client = i2c_new_probed_device(adapter, info, probe_addrs);  
  13.     else  
  14.         client = i2c_new_device(adapter, info); //在此接口中会增加sysfs,会把驱动和设备关联起来,并会调用于I2C驱动中的probe接口  
  15.   
  16.     /* Note: by loading the module first we are certain that c->driver 
  17.        will be set if the driver was found. If the module was not loaded 
  18.        first, then the i2c core tries to delay-load the module for us, 
  19.        and then c->driver is still NULL until the module is finally 
  20.        loaded. This delay-load mechanism doesn't work if other drivers 
  21.        want to use the i2c device, so explicitly loading the module 
  22.        is the best alternative. */  
  23.     if (client == NULL || client->driver == NULL)  
  24.         goto error;  
  25.   
  26.     /* Lock the module so we can safely get the v4l2_subdev pointer */  
  27.     if (!try_module_get(client->driver->driver.owner))  
  28.         goto error;  
  29.     sd = i2c_get_clientdata(client);//获取I2C驱动中的结构变量  
  30.   
  31.     /* Register with the v4l2_device which increases the module's 
  32.        use count as well. */  
  33.     if (v4l2_device_register_subdev(v4l2_dev, sd))//  
  34.         sd = NULL;  
  35.     /* Decrease the module use count to match the first try_module_get. */  
  36.     module_put(client->driver->driver.owner);  
  37.   
  38.     if (sd) {  
  39.         /* We return errors from v4l2_subdev_call only if we have the 
  40.            callback as the .s_config is not mandatory */  
  41.         int err = v4l2_subdev_call(sd, core, s_config,  
  42.                 info->irq, info->platform_data);  //调用I2C驱动中定义的接口,来配置I2C CAMERA。  
  43.   
  44.         if (err && err != -ENOIOCTLCMD) {  
  45.             v4l2_device_unregister_subdev(sd);  
  46.             sd = NULL;  
  47.         }  
  48.     }  
  49.     .............  
  50.     return sd;  
  51. }  
  52.   
  53. struct i2c_client *  
  54. i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  
  55. {  
  56.     struct i2c_client   *client;  
  57.     int         status;  
  58.   
  59.     client = kzalloc(sizeof *client, GFP_KERNEL); //为新的I2C client分配空间  
  60.     if (!client)  
  61.         return NULL;  
  62.   
  63.     client->adapter = adap;  
  64.   
  65.     client->dev.platform_data = info->platform_data;  
  66.   
  67.     if (info->archdata)  
  68.         client->dev.archdata = *info->archdata;  
  69.   
  70.     client->flags = info->flags;  
  71.     client->addr = info->addr;  
  72.     client->irq = info->irq;  
  73.   
  74.     strlcpy(client->name, info->type, sizeof(client->name));  
  75.   
  76.     /* Check for address business */  
  77.     status = i2c_check_addr(adap, client->addr); //检查I2C设备是否已经加载过了  
  78.     if (status)  
  79.         goto out_err;  
  80.   
  81.     client->dev.parent = &client->adapter->dev;  
  82.     client->dev.bus = &i2c_bus_type;   //注册I2C总线处理回调函数,如果探测到设备后会调用于其中的接口  
  83.     client->dev.type = &i2c_client_type; //注册引sysfs有关的接口  
  84.   
  85.     dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),  
  86.              client->addr);  
  87.     status = device_register(&client->dev);//注册I2C设备  
  88.     if (status)  
  89.         goto out_err;  
  90.   
  91.     dev_dbg(&adap->dev, "client [%s] registered with bus id %s/n",  
  92.         client->name, dev_name(&client->dev));  
  93.     printk("%s , %d /n", __FUNCTION__, __LINE__);  
  94.     return client;  
  95.   
  96. out_err:  
  97.     dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "  
  98.         "(%d)/n", client->name, client->addr, status);  
  99.     kfree(client);  
  100.     return NULL;  
  101. }  
  102.   
  103. int device_register(struct device *dev)  
  104. {  
  105.     device_initialize(dev); //初始化设备的相关成员  
  106.     return device_add(dev);  
  107. }  
  108.   
  109. int device_add(struct device *dev)  
  110. {  
  111.     ...........  
  112.       
  113.     bus_probe_device(dev); //从总线上探测设备  
  114.       
  115.  ...........  
  116. }  
  117.   
  118. void bus_probe_device(struct device *dev)  
  119. {  
  120.     struct bus_type *bus = dev->bus;  
  121.     int ret;  
  122.   
  123.     if (bus && bus->p->drivers_autoprobe) {  
  124.         ret = device_attach(dev);//把驱动和设备关联起来  
  125.         WARN_ON(ret < 0);  
  126.     }  
  127. }  
  128.   
  129. int device_attach(struct device *dev)  
  130. {  
  131.     int ret = 0;  
  132.   
  133.     down(&dev->sem);  
  134.     if (dev->driver) {  
  135.         ret = device_bind_driver(dev);  
  136.         if (ret == 0)  
  137.             ret = 1;  
  138.         else {  
  139.             dev->driver = NULL;  
  140.             ret = 0;  
  141.         }  
  142.     } else {  
  143.         pm_runtime_get_noresume(dev);  
  144.         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); //会调用于此  
  145.         pm_runtime_put_sync(dev);  
  146.     }  
  147.     up(&dev->sem);  
  148.     return ret;  
  149. }  
  150.   
  151. static int __device_attach(struct device_driver *drv, void *data)  
  152. {  
  153.     struct device *dev = data;  
  154.   
  155.     if (!driver_match_device(drv, dev)) //找到驱动结构是名字匹配的设备  
  156.         return 0;  
  157.   
  158.     return driver_probe_device(drv, dev);   
  159. }  
  160.   
  161. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  162. {  
  163.     int ret = 0;  
  164.   
  165.     if (!device_is_registered(dev)) //检查驱动是否和设备已经关联  
  166.         return -ENODEV;  
  167.   
  168.     pr_debug("bus: '%s': %s: matched device %s with driver %s/n",  
  169.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  170.   
  171.     pm_runtime_get_noresume(dev);  
  172.     pm_runtime_barrier(dev);  
  173.     ret = really_probe(dev, drv); //设备驱动中的probe  
  174.     pm_runtime_put_sync(dev);  
  175.   
  176.     return ret;  
  177. }  
  178.   
  179. static int really_probe(struct device *dev, struct device_driver *drv)  
  180. {  
  181.     int ret = 0;  
  182.   
  183.     atomic_inc(&probe_count);  
  184.     pr_debug("bus: '%s': %s: probing driver %s with device %s/n",  
  185.          drv->bus->name, __func__, drv->name, dev_name(dev));  
  186.     WARN_ON(!list_empty(&dev->devres_head));  
  187.   
  188.     dev->driver = drv;  
  189.     //增加驱动在sysfs 中的文件  
  190.     if (driver_sysfs_add(dev)) {  
  191.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n",  
  192.             __func__, dev_name(dev));  
  193.         goto probe_failed;  
  194.     }  
  195.     //调用前面注册的总线上的probe,然后在其中会调用到驱动中的probe函数  
  196.     if (dev->bus->probe) {  
  197.         ret = dev->bus->probe(dev);  
  198.         if (ret)  
  199.             goto probe_failed;  
  200.     } else if (drv->probe) {  
  201.         ret = drv->probe(dev);  
  202.         if (ret)  
  203.             goto probe_failed;  
  204.     }  
  205.     //驱动和设备绑定  
  206.     driver_bound(dev);  
  207.     ret = 1;  
  208.     pr_debug("bus: '%s': %s: bound device %s to driver %s/n",  
  209.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  210.     goto done;  
  211.   
  212. probe_failed:  
  213.     devres_release_all(dev);  
  214.     driver_sysfs_remove(dev);  
  215.     dev->driver = NULL;  
  216.   
  217.     if (ret != -ENODEV && ret != -ENXIO) {  
  218.         /* driver matched but the probe failed */  
  219.         printk(KERN_WARNING  
  220.                "%s: as probe of %s failed with error %d/n",  
  221.                drv->name, dev_name(dev), ret);  
  222.     }  
  223.     /* 
  224.      * Ignore errors returned by ->probe so that the next driver can try 
  225.      * its luck. 
  226.      */  
  227.     ret = 0;  
  228. done:  
  229.     atomic_dec(&probe_count);  
  230.     wake_up(&probe_waitqueue);  
  231.     return ret;  
  232. }  

阅读(3489) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~