通过私有数据实现对象的继承或者关联
向子系统注新对象时,新对象的私有数据和框架层的基础对象复合成新对象。
基础架构一般会提供create方法,实现这个对象的创建并设置私有数据。
驱动模块得到创建的新对象之后进一步设置私有数据。
下面是一个虚拟无线网络设备的创建过程:
/* Function that creates wiphy context and net_device with wireless_dev.
* wiphy/net_device/wireless_dev is basic interfaces for the kernel to interact with driver as wireless one.
* It returns driver's main "navifly" context. */
static struct navifly_context *navifly_create_context(void) {
struct navifly_context *ret = NULL;
struct navifly_wiphy_priv_context *wiphy_data = NULL;
struct navifly_ndev_priv_context *ndev_data = NULL;
/* allocate for navifly context*/
ret = kmalloc(sizeof(*ret), GFP_KERNEL);
if (!ret) {
goto l_error;
}
/* allocate wiphy context, also it possible just to use wiphy_new() function.
* wiphy should represent physical FullMAC wireless device.
* One wiphy can have serveral network interfaces - for that u need to implement add_virtual_intf() and co. from cfg80211_ops. */
ret->wiphy = wiphy_new_nm(&nvf_cfg_ops, sizeof(struct navifly_wiphy_priv_context), WIPHY_NAME);
if (ret->wiphy == NULL) {
goto l_error_wiphy;
}
/* save navifly context in wiphy private data. */
wiphy_data = wiphy_get_navi_context(ret->wiphy);
wiphy_data->navi = ret;
/* set device object as wiphy "parent", I dont have any device yet. */
/* set_wiphy_dev(ret->wiphy, dev); */
/* wiphy should determinate it type */
/* add other required types like "BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP)" etc. */
ret->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
/* wiphy should have at least 1 band. */
/* fill also NL80211_BAND_5GHZ if required, in this small example I use only 1 band with 1 "channel" */
ret->wiphy->bands[NL80211_BAND_2GHZ] = &nf_band_2ghz;
/* scan - if ur device supports "scan" u need to define max_scan_ssids at least. */
ret->wiphy->max_scan_ssids = 69;
/* register wiphy, if everything ok - there should be another wireless device in system.
* use command:
* $ iw list
* Wiphy navifly
* ...
* */
if (wiphy_register(ret->wiphy) < 0) {
goto l_error_wiphy_register;
}
/* allocate network device context. */
ret->ndev = alloc_netdev(sizeof(*ndev_data), NDEV_NAME, NET_NAME_ENUM, ether_setup);
if (ret->ndev == NULL) {
goto l_error_alloc_ndev;
}
/* fill private data of network context.*/
ndev_data = ndev_get_navi_context(ret->ndev);
ndev_data->navi = ret;
/* fill wireless_dev context.
* wireless_dev with net_device can be represented as inherited class of single net_device. */
ndev_data->wdev.wiphy = ret->wiphy;
ndev_data->wdev.netdev = ret->ndev;
ndev_data->wdev.iftype = NL80211_IFTYPE_STATION;
ret->ndev->ieee80211_ptr = &ndev_data->wdev;
/* set device object for net_device */
/* SET_NETDEV_DEV(ret->ndev, wiphy_dev(ret->wiphy)); */
/* set network device hooks. It should implement ndo_start_xmit() at least. */
ret->ndev->netdev_ops = &nvf_ndev_ops;
/* Add here proper net_device initialization. */
/* register network device. If everything ok, there should be new network device:
* $ ip a
* ...
* 4: navifly0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
* link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
* ...
* */
if (register_netdev(ret->ndev)) {
goto l_error_ndev_register;
}
return ret;
l_error_ndev_register:
free_netdev(ret->ndev);
l_error_alloc_ndev:
wiphy_unregister(ret->wiphy);
l_error_wiphy_register:
wiphy_free(ret->wiphy);
l_error_wiphy:
kfree(ret);
l_error:
return NULL;
}