1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Loopback IEEE 802.15.4 interface 4 * 5 * Copyright 2007-2012 Siemens AG 6 * 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 22 static int numlbs = 2; 23 24 static LIST_HEAD(fakelb_phys); 25 static DEFINE_MUTEX(fakelb_phys_lock); 26 27 static LIST_HEAD(fakelb_ifup_phys); 28 static DEFINE_RWLOCK(fakelb_ifup_phys_lock); 29 30 struct 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 42 static int fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level) 43 { 44 WARN_ON(!level); 45 *level = 0xbe; 46 47 return 0; 48 } 49 50 static 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 61 static 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 85 static 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 97 static 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 107 static int 108 fakelb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on) 109 { 110 return 0; 111 } 112 113 static 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. */ 124 module_param(numlbs, int, 0); 125 MODULE_PARM_DESC(numlbs, " number of pseudo devices"); 126 127 static 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 189 err_reg: 190 ieee802154_free_hw(phy->hw); 191 return err; 192 } 193 194 static 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 202 static 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 216 err_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 224 static int 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 return 0; 233 } 234 235 static struct platform_device *ieee802154fake_dev; 236 237 static struct platform_driver ieee802154fake_driver = { 238 .probe = fakelb_probe, 239 .remove = fakelb_remove, 240 .driver = { 241 .name = "ieee802154fakelb", 242 }, 243 }; 244 245 static __init int fakelb_init_module(void) 246 { 247 ieee802154fake_dev = platform_device_register_simple( 248 "ieee802154fakelb", -1, NULL, 0); 249 250 pr_warn("fakelb driver is marked as deprecated, please use mac802154_hwsim!\n"); 251 252 return platform_driver_register(&ieee802154fake_driver); 253 } 254 255 static __exit void fake_remove_module(void) 256 { 257 platform_driver_unregister(&ieee802154fake_driver); 258 platform_device_unregister(ieee802154fake_dev); 259 } 260 261 module_init(fakelb_init_module); 262 module_exit(fake_remove_module); 263 MODULE_LICENSE("GPL"); 264