无线传感网:ieee802154与6lowpan在kernel 3.0/4.0的框架分析

  kernel 4.0 ieee802154 6lowpan 框架


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1Kernel 3.0自上而下层次:

 Netlink  接口

.mac 层的netlink

mlme层 Ops 接口

Kenrel 3.0 并没有实现:ieee802154_mlme_ops的驱动;如下是一个驱动例子 fake_mlme;

核心层网络设备驱动实例化

两种类型的网络设备驱动:

@net_device_ops mac802154_wpan_ops;

@net_device_ops mac802154_monitor_ops;

硬件驱动ieee802154_ops

struct ieee802154_ops {

struct module        *owner;

int                (*start)(struct ieee802154_dev *dev);

void                (*stop)(struct ieee802154_dev *dev);

int                (*xmit)(struct ieee802154_dev *dev,

 

2Kernel4 .0自上而下层次:

Netlink  接口

包括 mac 层的netlinknl802154

mlme层 Ops 接口

Kenrel 3.0 并没有实现:ieee802154_mlme_ops的驱动;如下是一个驱动例子 fake_mlme;

cfg802154接口

以上的netlink 接口都是,通过cfg接口来完成对macphy的控制。

核心层网络设备驱动实例化

两种类型的网络设备驱动:

iface.c@net_device_ops mac802154_wpan_ops;

iface.c@net_device_ops mac802154_monitor_ops;

硬件驱动ieee802154_ops

由两层封装:ieee802154_local ieee802154_ops:

/* mac802154 device private data */

struct ieee802154_local {

struct ieee802154_hw hw;

const struct ieee802154_ops *ops;

 

…..

struct ieee802154_ops {

struct module        *owner;

int                (*start)(struct ieee802154_dev *dev);

void                (*stop)(struct ieee802154_dev *dev);

int                (*xmit)(struct ieee802154_dev *dev,

 

   Netlink 接口

2.0  kernel 4.0 内核的netlink接口

两种netlink接口:

接口1.mac 层的netlink :名称:#define IEEE802154_NL_NAME "802.15.4MAC"

它由有两部分组成:

macnetlink

用于让用户层程序控制ieee802154设备(协调器,beacon设备)的,激活/关闭/扫描/

phynetlink

Kernel3.0用于让用户层程序可以,增加/添加/一个ieee802.15.4设备;列出当前系统的ieee802.15.4设备,

kernel4.0是用于用户层,可以增加/添加/一个虚拟ieee802.15.4设备。

netlink.c@定义netlink接口:

static const struct genl_ops ieee8021154_ops[] = {

/*see nl-phy.c */

IEEE802154_DUMP(IEEE802154_LIST_PHY,ieee802154_list_phy,

ieee802154_dump_phy),

IEEE802154_OP(IEEE802154_ADD_IFACE,ieee802154_add_iface),

IEEE802154_OP(IEEE802154_DEL_IFACE,ieee802154_del_iface),

/*see nl-mac.c */

IEEE802154_OP(IEEE802154_ASSOCIATE_REQ,ieee802154_associate_req),

IEEE802154_OP(IEEE802154_ASSOCIATE_RESP,ieee802154_associate_resp),

IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ,ieee802154_disassociate_req),

IEEE802154_OP(IEEE802154_SCAN_REQ,ieee802154_scan_req),

IEEE802154_OP(IEEE802154_START_REQ,ieee802154_start_req),

IEEE802154_DUMP(IEEE802154_LIST_IFACE,ieee802154_list_iface,

ieee802154_dump_iface),

IEEE802154_OP(IEEE802154_SET_MACPARAMS,ieee802154_set_macparams),

…..

nl-phy.c

phynetlink的接口定义;

nl-mac.c

macnetlink的接口定义;

 

接口2nl802154 (基于cfg802154)接口名称是:nl802154

用于对无线设备进行配置管理。

 

/net/ieee802154/nl802154.c@

static const structgenl_ops nl802154_ops[] = {

{

.cmd= NL802154_CMD_GET_WPAN_PHY,

.doit= nl802154_get_wpan_phy,

.dumpit= nl802154_dump_wpan_phy,

.done= nl802154_dump_wpan_phy_done,

.policy= nl802154_policy,

/*can be retrieved by unprivileged users */

.internal_flags= NL802154_FLAG_NEED_WPAN_PHY |

  NL802154_FLAG_NEED_RTNL,

},

{

.cmd= NL802154_CMD_GET_INTERFACE,

.doit= nl802154_get_interface,

.dumpit= nl802154_dump_interface,

.policy= nl802154_policy,

/*can be retrieved by unprivileged users */

.internal_flags= NL802154_FLAG_NEED_WPAN_DEV |

  NL802154_FLAG_NEED_RTNL,

},

……

 

2.1 kernel 3.0 注册的netlink接口

   

两者有一个共同的family 

注册一个family 

int __initieee802154_nl_init(void)

{

int rc;

 

rc = genl_register_family(&nl802154_family);

if (rc)

 

 

2.1.1 phynetlink的注册:

nl-phy.c@

staticstruct genl_ops ieee802154_phy_ops[] = {

IEEE802154_DUMP(IEEE802154_LIST_PHY, ieee802154_list_phy,

ieee802154_dump_phy),

IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),

IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),

};

 

/*

 * No need to unregister as familyunregistration will do it.

 */

intnl802154_phy_register(void)

{

int i;

int rc;

 

for (i = 0; i < ARRAY_SIZE(ieee802154_phy_ops); i++) {

rc = genl_register_ops(&nl802154_family,

&ieee802154_phy_ops[i]);

if (rc)

return rc;

}

 

return 0;

}

会操作到对应的 硬件驱动--->

2.1.2 macnetlink

step1.注册mc_group:ieee802154_coord_mcgrp和 ieee802154_beacon_mcgrp family

  注册ops family

nl-mac.c

intnl802154_mac_register(void)

{

int i;

int rc;

 

rc = genl_register_mc_group(&nl802154_family,

&ieee802154_coord_mcgrp);

if (rc)

return rc;

 

rc = genl_register_mc_group(&nl802154_family,

&ieee802154_beacon_mcgrp);

if (rc)

return rc;

 

for (i = 0; i < ARRAY_SIZE(ieee802154_coordinator_ops); i++) {

rc = genl_register_ops(&nl802154_family,

&ieee802154_coordinator_ops[i]);

if (rc)

return rc;

}

 

return 0;

}

Step2:定义genl_ops的ops接口:应用层  通过gennl接口就可以实现 控制ieee802154设备。

staticstruct genl_opsieee802154_coordinator_ops[] = {

IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),

IEEE802154_OP(IEEE802154_ASSOCIATE_RESP,ieee802154_associate_resp),

IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ,ieee802154_disassociate_req),

IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req),

IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),

IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,

ieee802154_dump_iface),

};

跟踪代码:genl_ops 最终会 调起mlme Ops 接口: ieee802154_mlme_ops;

 

 

  cfg 接口:cfg802154_ops,以上的netlink 接口都是,通过cfg接口来完成对macphy的控制。

 

net/mac802154/cfg.c

const struct cfg802154_ops mac802154_config_ops ={

.add_virtual_intf_deprecated= ieee802154_add_iface_deprecated,

.del_virtual_intf_deprecated= ieee802154_del_iface_deprecated,

.add_virtual_intf= ieee802154_add_iface,

.del_virtual_intf= ieee802154_del_iface,

.set_channel= ieee802154_set_channel,

.set_cca_mode= ieee802154_set_cca_mode,

.set_pan_id= ieee802154_set_pan_id,

.set_short_addr= ieee802154_set_short_addr,

.set_backoff_exponent= ieee802154_set_backoff_exponent,

.set_max_csma_backoffs= ieee802154_set_max_csma_backoffs,

.set_max_frame_retries= ieee802154_set_max_frame_retries,

.set_lbt_mode= ieee802154_set_lbt_mode,

};

 

   mlme Ops 接口:

3.0 kernel 4.0 内核

struct ieee802154_mlme_ops {

/*The following fields are optional (can be NULL). */

 

int(*assoc_req)(struct net_device *dev,

structieee802154_addr *addr,

u8channel, u8 page, u8 cap);

int(*assoc_resp)(struct net_device *dev,

structieee802154_addr *addr,

__le16short_addr, u8 status);

int(*disassoc_req)(struct net_device *dev,

structieee802154_addr *addr,

u8reason);

int(*start_req)(struct net_device *dev,

structieee802154_addr *addr,

u8channel, u8 page, u8 bcn_ord, u8 sf_ord,

u8pan_coord, u8 blx, u8 coord_realign);

int(*scan_req)(struct net_device *dev,

u8type, u32 channels, u8 page, u8 duration);

 

int(*set_mac_params)(struct net_device *dev,

      const struct ieee802154_mac_params*params);

void(*get_mac_params)(struct net_device *dev,

       struct ieee802154_mac_params *params);

 

struct ieee802154_llsec_ops *llsec;//新增 llsec接口 控制

 

/*The fields below are required. */

 

/*

 * FIXME: these should become the part ofPIB/MIB interface.

 * However we still don't have IB interface ofany kind

 */

__le16(*get_pan_id)(const struct net_device *dev);

__le16(*get_short_addr)(const struct net_device *dev);

u8(*get_dsn)(const struct net_device *dev);

};

1ieee802154_mlme_ops的实现:Mac_cmd.c

structieee802154_mlme_ops mac802154_mlme_wpan = {

.start_req= mac802154_mlme_start_req,

.get_pan_id= mac802154_dev_get_pan_id,

.get_short_addr= mac802154_dev_get_short_addr,

.get_dsn= mac802154_dev_get_dsn,

 

.llsec= &mac802154_llsec_ops,

 

.set_mac_params= mac802154_set_mac_params,

.get_mac_params= mac802154_get_mac_params,

};

存在问题:Scan_req/assoc_req/等 都没有实现,那么如何控制ieee802154设备的激活/关闭/扫描/

 

3.1 kernel 3,0 内核:

1.ops 数据结构定义:

structieee802154_mlme_ops {

/* The following fields are optional (can be NULL). */这部分不是必须

 

int (*assoc_req)(struct net_device *dev,

struct ieee802154_addr *addr,

u8 channel, u8 page, u8 cap);

int (*assoc_resp)(struct net_device *dev,

struct ieee802154_addr *addr,

u16 short_addr, u8 status);

int (*disassoc_req)(struct net_device *dev,

struct ieee802154_addr *addr,

u8 reason);

int (*start_req)(struct net_device *dev,

struct ieee802154_addr *addr,

u8 channel, u8 page, u8 bcn_ord, u8 sf_ord,

u8 pan_coord, u8 blx, u8 coord_realign);

int (*scan_req)(struct net_device *dev,

u8 type, u32 channels, u8 page, u8 duration);

 

/* The fields below are required. *///如下是必须部分

 

struct wpan_phy *(*get_phy)(const struct net_device *dev);

 

/*

 * FIXME: these should becomethe part of PIB/MIB interface.

 * However we still don'thave IB interface of any kind

 */

u16 (*get_pan_id)(const struct net_device *dev);

u16 (*get_short_addr)(const struct net_device *dev);

u8 (*get_dsn)(const struct net_device *dev);

};

 

2.MLME驱动实现

1)fakehard.c --这是一个编程实例;

staticstruct ieee802154_mlme_ops fake_mlme = {

.assoc_req = fake_assoc_req,

.assoc_resp = fake_assoc_resp,

.disassoc_req = fake_disassoc_req,

.start_req = fake_start_req,

.scan_req = fake_scan_req,

 

.get_phy = fake_get_phy,

 

.get_pan_id = fake_get_pan_id,

.get_short_addr = fake_get_short_addr,

.get_dsn = fake_get_dsn,

};

2kernel 3.0实现了mlme驱动:

struct ieee802154_mlme_ops mac802154_mlme_wpan = {

.get_phy = mac802154_get_phy,

.start_req = mac802154_mlme_start_req,

.get_pan_id = mac802154_dev_get_pan_id,

.get_short_addr = mac802154_dev_get_short_addr,

.get_dsn = mac802154_dev_get_dsn,

};

存在问题:Scan_req/assoc_req/等 都没有实现,那么如何控制ieee802154设备的激活/关闭/扫描/

================================================================================================================

1scan分析:

----1 发送scan请求:

scan的类型有:/* Scan Type */  

#define MAC_SCAN_ED                

 0    

Energy detect scan.  The device will tune to each channel and perform and energy measurement.  The list of channels and their associated measurements will be returned at the end of the scan 

 

#define MAC_SCAN_ACTIVE   

 1  

 Active scan.  The device tunes to each channel, sends a beacon request and listens for beacons.  The PAN descriptors are returned  at the end of the scan 

主动扫描;作为coordinate节点时候使用,用来建立PAN

 

#define MAC_SCAN_PASSIVE  

  2 

 Passive scan.  The device tunes to each channel and listens for beacons.  The PAN descriptors are returned at the end of the scan  

被动扫描;作为设备节点时候使用,用来加入已经存在的PAN

#define MAC_SCAN_ORPHAN  

  3

  Orphan scan.  The device tunes to each channel and sends an orphan notification to try and find its coordinator.  The status is returned at the end of the scan 

 

Kenrel 3.0 定义在

ieee802154_netdev.h;

Zigbee-kernel定义在

mac_def.h;

 

驱动编程分两步:

static intfake_scan_req(struct net_device *dev, u8 type, u32 channels,

u8page, u8 duration)

{

u8edl[27] = {};

步骤1 增加相关 scan的处理代码

//比如调起硬件驱动层的ops ieee802154_ops.

步骤2:返回nl状态

returnieee802154_nl_scan_confirm(dev,IEEE802154_SUCCESS, type,channels, page,type == IEEE802154_MAC_SCAN_ED ? edl :NULL);

}

参考 Zigbee-kernel例子:

intieee80215_mlme_scan_req(struct net_device *dev, u8 type, u32 channels, u8duration)

{

structieee80215_priv *hw = ieee80215_slave_get_hw(dev);

structscan_work *work;

 

pr_debug("%s()\n",__func__);

 

if(duration > 14)

gotoinval;

if(channels & hw->hw.channel_mask)

gotoinval;

 

work= kzalloc(sizeof(struct scan_work), GFP_KERNEL);

if(!work)

gotoinval;

 

work->dev= dev;

work->channels= channels;

work->duration= duration;

work->type= type;

 

switch(type) {

caseIEEE80215_MAC_SCAN_ED:

work->scan_ch= scan_ed;

break;

caseIEEE80215_MAC_SCAN_ACTIVE:

work->scan_ch= scan_active;

break;

caseIEEE80215_MAC_SCAN_PASSIVE:

work->scan_ch= scan_passive;

break;

caseIEEE80215_MAC_SCAN_ORPHAN:

work->scan_ch= scan_orphan;

break;

default:

pr_debug("%s():invalid type %d\n", __func__, type);

gotoinval;

}

 

INIT_WORK(&work->work,scanner);

queue_work(hw->dev_workqueue,&work->work);

 

return0;

 

inval:

ieee80215_nl_scan_confirm(dev,IEEE80215_INVALID_PARAMETER, type, channels,//发送scan confirm失败信息到 Netlink

NULL/*,NULL */);

return-EINVAL;

}

 

static int scan_active(struct scan_work *work, intchannel, u8 duration)

{

intret;

pr_debug("activescan channel %d duration %d\n", channel, duration);

ret= ieee80215_send_beacon_req(work->dev);

if(ret < 0)

returnPHY_ERROR;

returnscan_passive(work, channel, duration);

}

 

硬件驱动 ops

4.0 kernel 4.0上的接口

1.net核心层net_device_ops:

  

关键ops封装在const struct net_device_ops *netdev_ops;

如何注册一个网络设备呢?

----需要通过   IEEE 802.15.4 implementation ieee80215.4驱动)来注册产生一个面向 核心层的网络设备;

注册网络设备的流程“

例如:mrf24j40.c@mrf24j40_probe()芯片调用ieee802154_register_device()注册到IEEE802.15.4 implementation(可以理解成这是一个驱动);立即产生一个网络设备:

static int mrf24j40_probe(struct spi_device *spi){

…..

/* Register with the802154 subsystem */

 

devrec->hw =ieee802154_alloc_hw(0, &mrf24j40_ops);

if (!devrec->hw)

gotoerr_ret;

 

devrec->hw->priv= devrec;

devrec->hw->parent= &devrec->spi->dev;

devrec->hw->phy->channels_supported[0]= CHANNEL_MASK;

devrec->hw->flags= IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |

    IEEE802154_HW_AFILT;

 

dev_dbg(printdev(devrec),"registered mrf24j40\n");

ret = ieee802154_register_hw(devrec->hw);---->ieee802154_if_add()----->register_netdevice()

}

main.c@ieee802154_register_hw(devrec->hw)

iface.c@structnet_device *ieee802154_if_add(struct ieee802154_local *local, const char *name,

  enumnl802154_iftype type, __le64 extended_addr)

{

….

//设备类型

switch (type) {

caseNL802154_IFTYPE_NODE:

ndev->type= ARPHRD_IEEE802154;

if(ieee802154_is_valid_extended_addr(extended_addr))

ieee802154_le64_to_be64(ndev->dev_addr,&extended_addr);

else

memcpy(ndev->dev_addr,ndev->perm_addr,

       IEEE802154_EXTENDED_ADDR_LEN);

break;

case NL802154_IFTYPE_MONITOR:

ndev->type= ARPHRD_IEEE802154_MONITOR;

break;

default:

ret= -EINVAL;

gotoerr;

}

 

/*TODO check this */

SET_NETDEV_DEV(ndev,&local->phy->dev);

sdata= netdev_priv(ndev);

ndev->ieee802154_ptr= &sdata->wpan_dev;

memcpy(sdata->name,ndev->name, IFNAMSIZ);

sdata->dev= ndev;

sdata->wpan_dev.wpan_phy= local->hw.phy;

sdata->local= local;

 

/*setup type-dependent data */

ret = ieee802154_setup_sdata(sdata, type);//设置 核心网络设备的ops

if(ret)

gotoerr;

 

ret= register_netdevice(ndev);

。。。。

}

 

 

2..设备层的ops

由两层封装:ieee802154_local ieee802154_ops:

/* mac802154 device private data */

struct ieee802154_local {

struct ieee802154_hw hw;

const struct ieee802154_ops *ops;

 

…..

struct ieee802154_ops {

struct module        *owner;

int                (*start)(struct ieee802154_dev *dev);

void                (*stop)(struct ieee802154_dev *dev);

int                (*xmit)(struct ieee802154_dev *dev,

struct sk_buff *skb);

int                (*ed)(struct ieee802154_dev *dev, u8 *level);

int                (*set_channel)(struct ieee802154_dev *dev,

       int page,

       int channel);

int                (*set_hw_addr_filt)(struct ieee802154_dev *dev,

  struct ieee802154_hw_addr_filt *filt,

    unsigned long changed);

int                (*ieee_addr)(struct ieee802154_dev *dev,

     u8 addr[IEEE802154_ADDR_LEN]);

};

实例化:static struct ieee802154_ops mrf24j40_ops = {

.owner= THIS_MODULE,

.xmit= mrf24j40_tx,

.ed= mrf24j40_ed,

.start= mrf24j40_start,

.stop= mrf24j40_stop,

.set_channel= mrf24j40_set_channel,

.set_hw_addr_filt= mrf24j40_filter,

};

所以 Kernel 4.0的驱动流程是:

系统级SPI

----->

驱动层

-->>>

芯片层

net核心层

---->

const struct net_device_ops *netdev_ops;

-->>>

ieee802154_local  ---ieee802154_ops

核心层

---->

两种类型的网络设备驱动:

iface.c@net_device_ops mac802154_wpan_ops;

iface.c@net_device_ops mac802154_monitor_ops;

-->>>

static struct ieee802154_ops mrf24j40_ops = {

.owner = THIS_MODULE,

.xmit = mrf24j40_tx,

.ed = mrf24j40_ed,

.start = mrf24j40_start,

.stop = mrf24j40_stop,

.set_channel = mrf24j40_set_channel,

.set_hw_addr_filt = mrf24j40_filter,

};

 

4.1 Kernel 3.10上的接口

分为两个封装层次:

1.net核心层net_device_ops:

  

关键ops封装在const struct net_device_ops *netdev_ops;

如何注册一个网络设备呢?

----需要通过   IEEE 802.15.4 implementation ieee80215.4驱动)来注册产生一个面向 核心层的网络设备;

 

 

注册网络设备的流程:

例如:mrf24j40.c@mrf24j40_probe()芯片调用ieee802154_register_device()注册到IEEE802.15.4 implementation(可以理解成这是一个驱动);但是还不会立即产生一个网络设备:

int ieee802154_register_device(structieee802154_dev *dev)

{

struct mac802154_priv *priv = mac802154_to_priv(dev);

int rc = -ENOMEM;

 

priv->dev_workqueue =

create_singlethread_workqueue(wpan_phy_name(priv->phy));

if (!priv->dev_workqueue)

goto out;

 

wpan_phy_set_dev(priv->phy, priv->hw.parent);

 

priv->phy->add_iface = mac802154_add_iface;

 

然后  需要用户程序通过phynetlink  接口ieee802154_add_iface()调起:phy->add_iface(phy,devname, type);---》mac802154_add_iface();

static struct net_device * mac802154_add_iface(struct wpan_phy *phy, const char *name,int type)

{

struct net_device *dev;

int err = -ENOMEM;

//设备类型

switch (type) {

case IEEE802154_DEV_MONITOR://检测类型设备

dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),

   name,mac802154_monitor_setup);

break;

case IEEE802154_DEV_WPAN://一般设备

dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),

   name,mac802154_wpan_setup);

break;

default:

dev = NULL;

err = -EINVAL;

break;

}

if (!dev)

goto err;

 

err = mac802154_netdev_register(phy,dev);----》register_netdev()注册核心层的网络设备’

。。。。

}

最后  注册  net_device_ops:

voidmac802154_wpan_setup(struct net_device *dev)

{

struct mac802154_sub_if_data *priv;

 

dev->addr_len                =IEEE802154_ADDR_LEN;

memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);

 

dev->hard_header_len        =MAC802154_FRAME_HARD_HEADER_LEN;

dev->header_ops                =&mac802154_header_ops;

dev->needed_tailroom        =2; /* FCS */

dev->mtu                =IEEE802154_MTU;

dev->tx_queue_len        =300;

dev->type                =ARPHRD_IEEE802154;

dev->flags                =IFF_NOARP | IFF_BROADCAST;

dev->watchdog_timeo        =0;

 

dev->destructor                =free_netdev;

dev->netdev_ops                =&mac802154_wpan_ops;//网络设备驱动ops

dev->ml_priv                =&mac802154_mlme_wpan;//MLME驱动 ops

}

staticconst struct net_device_ops mac802154_wpan_ops = {

.ndo_open                =mac802154_slave_open,

.ndo_stop                =mac802154_slave_close,

.ndo_start_xmit                =mac802154_wpan_xmit,

.ndo_do_ioctl                =mac802154_wpan_ioctl,

.ndo_set_mac_address        =mac802154_wpan_mac_addr,

};

 

 

2..设备层的ops

struct ieee802154_ops {

struct module        *owner;

int                (*start)(struct ieee802154_dev *dev);

void                (*stop)(struct ieee802154_dev *dev);

int                (*xmit)(struct ieee802154_dev *dev,

struct sk_buff *skb);

int                (*ed)(struct ieee802154_dev *dev, u8 *level);

int                (*set_channel)(struct ieee802154_dev *dev,

       int page,

       int channel);

int                (*set_hw_addr_filt)(struct ieee802154_dev *dev,

  struct ieee802154_hw_addr_filt *filt,

    unsigned long changed);

int                (*ieee_addr)(struct ieee802154_dev *dev,

     u8 addr[IEEE802154_ADDR_LEN]);

};

实例化:static struct ieee802154_ops mrf24j40_ops ={

.owner = THIS_MODULE,

.xmit = mrf24j40_tx,

.ed = mrf24j40_ed,

.start = mrf24j40_start,

.stop = mrf24j40_stop,

.set_channel = mrf24j40_set_channel,

.set_hw_addr_filt = mrf24j40_filter,

};

 

所以 Kernel 3.10的驱动流程是:

系统级SPI

----->

驱动层

-->>>

芯片层

net核心层

---->

const struct net_device_ops *netdev_ops;

-->>>

ieee802154_ops

核心层

---->

wpan.c@net_device_ops mac802154_wpan_ops;

monitor.c@net_device_ops mac802154_monitor_ops;

-->>>

static struct ieee802154_ops mrf24j40_ops = {

.owner = THIS_MODULE,

.xmit = mrf24j40_tx,

.ed = mrf24j40_ed,

.start = mrf24j40_start,

.stop = mrf24j40_stop,

.set_channel = mrf24j40_set_channel,

.set_hw_addr_filt = mrf24j40_filter,

};

 

4.2 zigbee-kernel 2.6上接口定义

分为两个封装层次:

1.核心设备层net_device_ops:

 

关键的操作接口有:

dev->open = ieee80215_master_open;

dev->stop = ieee80215_master_close;

dev->hard_start_xmit = ieee80215_master_hard_start_xmit;

dev->needed_headroom = hw->hw.extra_tx_headroom;

dev->get_stats = ieee80215_get_master_stats;

dev->do_ioctl = ieee80215_master_ioctl;

如何注册一个网络设备呢?

-----需要通过   IEEE 802.15.4 implementation ieee80215.4驱动)来注册产生一个面向 核心层的网络设备;

实现在main.c  ieee80215_register_netdev_master()

int ieee80215_register_netdev_master(structieee80215_priv *hw)

{

struct net_device *dev;

struct ieee80215_mnetdev_priv *priv;

 

dev = alloc_netdev(sizeof(struct ieee80215_mnetdev_priv),

"mwpan%d", ieee80215_netdev_setup_master);

if (!dev) {

printk(KERN_ERR "Failure to initialize master IEEE80215device\n");

return -ENOMEM;

}

priv = netdev_priv(dev);

priv->dev = dev;

priv->hw = hw;

hw->master = dev;

dev->open = ieee80215_master_open;

dev->stop = ieee80215_master_close;

dev->hard_start_xmit = ieee80215_master_hard_start_xmit;

dev->needed_headroom = hw->hw.extra_tx_headroom;

dev->get_stats = ieee80215_get_master_stats;

dev->do_ioctl = ieee80215_master_ioctl;

SET_NETDEV_DEV(dev, hw->hw.parent);

/* FIXME */

//        hw->ops->set_channel(&hw->hw,6);

register_netdev(dev);

return 0;

}

通过以上实例化struct net_device  的操作接口,来访问serial接口的ieee80215设备;

2.设备层的ops

struct ieee80215_ops {

struct module        *owner;

phy_status_t (*tx)(struct ieee80215_dev *dev, struct sk_buff *skb);

phy_status_t (*cca)(struct ieee80215_dev *dev);

phy_status_t (*ed)(struct ieee80215_dev *dev, u8 *level);

phy_status_t (*set_trx_state)(struct ieee80215_dev *dev, phy_status_t state);

phy_status_t (*set_channel)(struct ieee80215_dev *dev, int channel);

// FIXME: PIB get/set ???

};

注册设备ieee80215_register_device()到IEEE802.15.4 implementation(

可以理解成IEEE 802.15.4 implementation是面向linux网络核心层的驱动,ieee80215设备是ieee80215设备);

 

serial.c@

staticstruct ieee80215_ops serial_ops = {

.owner = THIS_MODULE,

.tx = ieee80215_serial_xmit,

.ed = ieee80215_serial_ed,

.cca = ieee80215_serial_cca,

.set_trx_state = ieee80215_serial_set_state,

.set_channel        =ieee80215_serial_set_channel,

};

所以zigbee-kernel 2.6访问流程是:

net核心层---->IEEE 802.15.4 implementation----->ieee80215_opsserial_ops.

 

如下:

staticvoid ieee80215_xmit_worker(struct work_struct *work)

{

struct xmit_work *xw = container_of(work, struct xmit_work,work);

phy_status_t res;

 

res =xw->priv->hw->ops->cca(&xw->priv->hw->hw);

if (res != PHY_IDLE)

goto out;

 

res = xw->priv->hw->ops->set_trx_state(&xw->priv->hw->hw,PHY_TX_ON);

if (res != PHY_SUCCESS && res != PHY_TX_ON) {

pr_debug("set_trx_state returned %d\n", res);

goto out;

}

 

res =xw->priv->hw->ops->tx(&xw->priv->hw->hw,xw->skb);

 

out:

// FIXME: result processing and/or requeue!!!

dev_kfree_skb(xw->skb);

 

xw->priv->hw->ops->set_trx_state(&xw->priv->hw->hw,PHY_RX_ON);

kfree(xw);

}

你可能感兴趣的:(android,kernel,stack,6lowpan,WSN)