brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · 2930141 Raw
264 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Loopback IEEE 802.15.4 interface4 *5 * Copyright 2007-2012 Siemens AG6 *7 * Written by:8 * Sergey Lapin <slapin@ossfans.org>9 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>10 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>11 */12 13#include <linux/module.h>14#include <linux/timer.h>15#include <linux/platform_device.h>16#include <linux/netdevice.h>17#include <linux/device.h>18#include <linux/spinlock.h>19#include <net/mac802154.h>20#include <net/cfg802154.h>21 22static int numlbs = 2;23 24static LIST_HEAD(fakelb_phys);25static DEFINE_MUTEX(fakelb_phys_lock);26 27static LIST_HEAD(fakelb_ifup_phys);28static DEFINE_RWLOCK(fakelb_ifup_phys_lock);29 30struct fakelb_phy {31	struct ieee802154_hw *hw;32 33	u8 page;34	u8 channel;35 36	bool suspended;37 38	struct list_head list;39	struct list_head list_ifup;40};41 42static int fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)43{44	WARN_ON(!level);45	*level = 0xbe;46 47	return 0;48}49 50static int fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)51{52	struct fakelb_phy *phy = hw->priv;53 54	write_lock_bh(&fakelb_ifup_phys_lock);55	phy->page = page;56	phy->channel = channel;57	write_unlock_bh(&fakelb_ifup_phys_lock);58	return 0;59}60 61static int fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)62{63	struct fakelb_phy *current_phy = hw->priv, *phy;64 65	read_lock_bh(&fakelb_ifup_phys_lock);66	WARN_ON(current_phy->suspended);67	list_for_each_entry(phy, &fakelb_ifup_phys, list_ifup) {68		if (current_phy == phy)69			continue;70 71		if (current_phy->page == phy->page &&72		    current_phy->channel == phy->channel) {73			struct sk_buff *newskb = pskb_copy(skb, GFP_ATOMIC);74 75			if (newskb)76				ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc);77		}78	}79	read_unlock_bh(&fakelb_ifup_phys_lock);80 81	ieee802154_xmit_complete(hw, skb, false);82	return 0;83}84 85static int fakelb_hw_start(struct ieee802154_hw *hw)86{87	struct fakelb_phy *phy = hw->priv;88 89	write_lock_bh(&fakelb_ifup_phys_lock);90	phy->suspended = false;91	list_add(&phy->list_ifup, &fakelb_ifup_phys);92	write_unlock_bh(&fakelb_ifup_phys_lock);93 94	return 0;95}96 97static void fakelb_hw_stop(struct ieee802154_hw *hw)98{99	struct fakelb_phy *phy = hw->priv;100 101	write_lock_bh(&fakelb_ifup_phys_lock);102	phy->suspended = true;103	list_del(&phy->list_ifup);104	write_unlock_bh(&fakelb_ifup_phys_lock);105}106 107static int108fakelb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)109{110	return 0;111}112 113static const struct ieee802154_ops fakelb_ops = {114	.owner = THIS_MODULE,115	.xmit_async = fakelb_hw_xmit,116	.ed = fakelb_hw_ed,117	.set_channel = fakelb_hw_channel,118	.start = fakelb_hw_start,119	.stop = fakelb_hw_stop,120	.set_promiscuous_mode = fakelb_set_promiscuous_mode,121};122 123/* Number of dummy devices to be set up by this module. */124module_param(numlbs, int, 0);125MODULE_PARM_DESC(numlbs, " number of pseudo devices");126 127static int fakelb_add_one(struct device *dev)128{129	struct ieee802154_hw *hw;130	struct fakelb_phy *phy;131	int err;132 133	hw = ieee802154_alloc_hw(sizeof(*phy), &fakelb_ops);134	if (!hw)135		return -ENOMEM;136 137	phy = hw->priv;138	phy->hw = hw;139 140	/* 868 MHz BPSK	802.15.4-2003 */141	hw->phy->supported.channels[0] |= 1;142	/* 915 MHz BPSK	802.15.4-2003 */143	hw->phy->supported.channels[0] |= 0x7fe;144	/* 2.4 GHz O-QPSK 802.15.4-2003 */145	hw->phy->supported.channels[0] |= 0x7FFF800;146	/* 868 MHz ASK 802.15.4-2006 */147	hw->phy->supported.channels[1] |= 1;148	/* 915 MHz ASK 802.15.4-2006 */149	hw->phy->supported.channels[1] |= 0x7fe;150	/* 868 MHz O-QPSK 802.15.4-2006 */151	hw->phy->supported.channels[2] |= 1;152	/* 915 MHz O-QPSK 802.15.4-2006 */153	hw->phy->supported.channels[2] |= 0x7fe;154	/* 2.4 GHz CSS 802.15.4a-2007 */155	hw->phy->supported.channels[3] |= 0x3fff;156	/* UWB Sub-gigahertz 802.15.4a-2007 */157	hw->phy->supported.channels[4] |= 1;158	/* UWB Low band 802.15.4a-2007 */159	hw->phy->supported.channels[4] |= 0x1e;160	/* UWB High band 802.15.4a-2007 */161	hw->phy->supported.channels[4] |= 0xffe0;162	/* 750 MHz O-QPSK 802.15.4c-2009 */163	hw->phy->supported.channels[5] |= 0xf;164	/* 750 MHz MPSK 802.15.4c-2009 */165	hw->phy->supported.channels[5] |= 0xf0;166	/* 950 MHz BPSK 802.15.4d-2009 */167	hw->phy->supported.channels[6] |= 0x3ff;168	/* 950 MHz GFSK 802.15.4d-2009 */169	hw->phy->supported.channels[6] |= 0x3ffc00;170 171	ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);172	/* fake phy channel 13 as default */173	hw->phy->current_channel = 13;174	phy->channel = hw->phy->current_channel;175 176	hw->flags = IEEE802154_HW_PROMISCUOUS;177	hw->parent = dev;178 179	err = ieee802154_register_hw(hw);180	if (err)181		goto err_reg;182 183	mutex_lock(&fakelb_phys_lock);184	list_add_tail(&phy->list, &fakelb_phys);185	mutex_unlock(&fakelb_phys_lock);186 187	return 0;188 189err_reg:190	ieee802154_free_hw(phy->hw);191	return err;192}193 194static void fakelb_del(struct fakelb_phy *phy)195{196	list_del(&phy->list);197 198	ieee802154_unregister_hw(phy->hw);199	ieee802154_free_hw(phy->hw);200}201 202static int fakelb_probe(struct platform_device *pdev)203{204	struct fakelb_phy *phy, *tmp;205	int err, i;206 207	for (i = 0; i < numlbs; i++) {208		err = fakelb_add_one(&pdev->dev);209		if (err < 0)210			goto err_slave;211	}212 213	dev_info(&pdev->dev, "added %i fake ieee802154 hardware devices\n", numlbs);214	return 0;215 216err_slave:217	mutex_lock(&fakelb_phys_lock);218	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)219		fakelb_del(phy);220	mutex_unlock(&fakelb_phys_lock);221	return err;222}223 224static void fakelb_remove(struct platform_device *pdev)225{226	struct fakelb_phy *phy, *tmp;227 228	mutex_lock(&fakelb_phys_lock);229	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)230		fakelb_del(phy);231	mutex_unlock(&fakelb_phys_lock);232}233 234static struct platform_device *ieee802154fake_dev;235 236static struct platform_driver ieee802154fake_driver = {237	.probe = fakelb_probe,238	.remove_new = fakelb_remove,239	.driver = {240			.name = "ieee802154fakelb",241	},242};243 244static __init int fakelb_init_module(void)245{246	ieee802154fake_dev = platform_device_register_simple(247			     "ieee802154fakelb", -1, NULL, 0);248 249	pr_warn("fakelb driver is marked as deprecated, please use mac802154_hwsim!\n");250 251	return platform_driver_register(&ieee802154fake_driver);252}253 254static __exit void fake_remove_module(void)255{256	platform_driver_unregister(&ieee802154fake_driver);257	platform_device_unregister(ieee802154fake_dev);258}259 260module_init(fakelb_init_module);261module_exit(fake_remove_module);262MODULE_DESCRIPTION("IEEE 802.15.4 loopback driver");263MODULE_LICENSE("GPL");264