IEEE 802.15.4 for Linux 详解 (WPAN设备注册和初始化)

在这章所说的设备注册和初始化是指WPAN网络设备的注册和初始化,而不是SPI总线设备的设备注册。下面这张图表示CC2420 probe函数中如何注册WPAN的过程。

image

下面详细讲解每个函数的作用:

1. IEEE 802.15.4_alloc_device

   1: struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
   2:         struct ieee802154_ops *ops)
   3: {
   4:     struct wpan_phy *phy;
   5:     struct ieee802154_priv *priv;
   6:  
   7:     phy = wpan_phy_alloc(ALIGN(sizeof(*priv), NETDEV_ALIGN) + priv_size);    // 给wpan_phy结构分配空间
   8:     if (!phy) {
   9:         printk(KERN_ERR "Failure to initialize master IEEE802154 devicen");
  10:         return NULL;
  11:     }
  12:  
  13:     priv = wpan_phy_priv(phy);
  14:     priv->hw.phy = priv->phy = phy;    // private数据和ieee802154_dev数据中wpan_phy初始化为相同的phy
  15:  
  16:     priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
  17:  
  18:     BUG_ON(!ops);
  19:     BUG_ON(!ops->xmit);
  20:     BUG_ON(!ops->ed);
  21:     BUG_ON(!ops->start);
  22:     BUG_ON(!ops->stop);
  23:  
  24:     priv->ops = ops;    // 芯片驱动所对应的操作
  25:  
  26:     INIT_LIST_HEAD(&priv->slaves);
  27:     mutex_init(&priv->slaves_mtx);
  28:  
  29:     return &priv->hw;
  30: }
  31: EXPORT_SYMBOL(ieee802154_alloc_device);

2. IEEE 802.15.4_register_device

   1: int ieee802154_register_device(struct ieee802154_dev *dev)
   2: {
   3:     struct ieee802154_priv *priv = ieee802154_to_priv(dev);
   4:     int rc;
   5:  
   6:     priv->dev_workqueue =
   7:         create_singlethread_workqueue(wpan_phy_name(priv->phy));
   8:     if (!priv->dev_workqueue) {
   9:         rc = -ENOMEM;
  10:         goto out;
  11:     }
  12:  
  13:     wpan_phy_set_dev(priv->phy, priv->hw.parent);
  14:  
  15:     priv->phy->add_iface = ieee802154_add_iface;    /* net_device在这个函数里初始化 */
  16:     priv->phy->del_iface = ieee802154_del_iface;
  17:  
  18:     rc = wpan_phy_register(priv->phy);    /* 注册WPAN物理层设备,实际上就是注册一个设备 
  19:                                                     device_add(&phy->dev);*/
  20:     if (rc < 0)
  21:         goto out_wq;
  22:  
  23:     return 0;
  24:  
  25: out_wq:
  26:     destroy_workqueue(priv->dev_workqueue);
  27: out:
  28:     return rc;
  29: }
  30: EXPORT_SYMBOL(ieee802154_register_device);
3. ieee802154_add_iface
   1: struct net_device *ieee802154_add_iface(struct wpan_phy *phy, const char *name, int type)
   2: {
   3:     struct net_device *dev;
   4:     int err = -ENOMEM;
   5:  
   6:     /* 根据设备工作模式来初始化net_dev结构 */
   7:     switch (type) {
   8:     case IEEE802154_DEV_WPAN:
   9:         dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data),
  10:                 name, ieee802154_wpan_setup);
  11:         break;
  12:     case IEEE802154_DEV_MONITOR:
  13:         dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data),
  14:                 name, ieee802154_monitor_setup);
  15:         break;
  16:     default:
  17:         dev = NULL;
  18:         err = -EINVAL;
  19:         break;
  20:     }
  21:     if (!dev)
  22:         goto err;
  23:  
  24:     err = ieee802154_netdev_register(phy, dev);    /* 注册IEEE 802.15.4 网络设备 */
  25:  
  26:     if (err)
  27:         goto err_free;
  28:  
  29:     dev_hold(dev); /* we return a device w/ incremented refcount */
  30:     return dev;
  31:  
  32: err_free:
  33:     free_netdev(dev);
  34: err:
  35:     return ERR_PTR(err);
  36: }

Leave a comment