1 /* 2 * Loopback IEEE 802.15.4 interface 3 * 4 * Copyright 2007-2012 Siemens AG 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Written by: 20 * Sergey Lapin <slapin@ossfans.org> 21 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 22 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 23 */ 24 25 #include <linux/module.h> 26 #include <linux/timer.h> 27 #include <linux/platform_device.h> 28 #include <linux/netdevice.h> 29 #include <linux/device.h> 30 #include <linux/spinlock.h> 31 #include <net/mac802154.h> 32 #include <net/wpan-phy.h> 33 34 static int numlbs = 1; 35 36 struct fakelb_dev_priv { 37 struct ieee802154_dev *dev; 38 39 struct list_head list; 40 struct fakelb_priv *fake; 41 42 spinlock_t lock; 43 bool working; 44 }; 45 46 struct fakelb_priv { 47 struct list_head list; 48 rwlock_t lock; 49 }; 50 51 static int 52 fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level) 53 { 54 might_sleep(); 55 BUG_ON(!level); 56 *level = 0xbe; 57 58 return 0; 59 } 60 61 static int 62 fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel) 63 { 64 pr_debug("set channel to %d\n", channel); 65 66 might_sleep(); 67 dev->phy->current_page = page; 68 dev->phy->current_channel = channel; 69 70 return 0; 71 } 72 73 static void 74 fakelb_hw_deliver(struct fakelb_dev_priv *priv, struct sk_buff *skb) 75 { 76 struct sk_buff *newskb; 77 78 spin_lock(&priv->lock); 79 if (priv->working) { 80 newskb = pskb_copy(skb, GFP_ATOMIC); 81 ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc); 82 } 83 spin_unlock(&priv->lock); 84 } 85 86 static int 87 fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) 88 { 89 struct fakelb_dev_priv *priv = dev->priv; 90 struct fakelb_priv *fake = priv->fake; 91 92 might_sleep(); 93 94 read_lock_bh(&fake->lock); 95 if (priv->list.next == priv->list.prev) { 96 /* we are the only one device */ 97 fakelb_hw_deliver(priv, skb); 98 } else { 99 struct fakelb_dev_priv *dp; 100 list_for_each_entry(dp, &priv->fake->list, list) { 101 if (dp != priv && 102 (dp->dev->phy->current_channel == 103 priv->dev->phy->current_channel)) 104 fakelb_hw_deliver(dp, skb); 105 } 106 } 107 read_unlock_bh(&fake->lock); 108 109 return 0; 110 } 111 112 static int 113 fakelb_hw_start(struct ieee802154_dev *dev) { 114 struct fakelb_dev_priv *priv = dev->priv; 115 int ret = 0; 116 117 spin_lock(&priv->lock); 118 if (priv->working) 119 ret = -EBUSY; 120 else 121 priv->working = 1; 122 spin_unlock(&priv->lock); 123 124 return ret; 125 } 126 127 static void 128 fakelb_hw_stop(struct ieee802154_dev *dev) { 129 struct fakelb_dev_priv *priv = dev->priv; 130 131 spin_lock(&priv->lock); 132 priv->working = 0; 133 spin_unlock(&priv->lock); 134 } 135 136 static struct ieee802154_ops fakelb_ops = { 137 .owner = THIS_MODULE, 138 .xmit = fakelb_hw_xmit, 139 .ed = fakelb_hw_ed, 140 .set_channel = fakelb_hw_channel, 141 .start = fakelb_hw_start, 142 .stop = fakelb_hw_stop, 143 }; 144 145 /* Number of dummy devices to be set up by this module. */ 146 module_param(numlbs, int, 0); 147 MODULE_PARM_DESC(numlbs, " number of pseudo devices"); 148 149 static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake) 150 { 151 struct fakelb_dev_priv *priv; 152 int err; 153 struct ieee802154_dev *ieee; 154 155 ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops); 156 if (!ieee) 157 return -ENOMEM; 158 159 priv = ieee->priv; 160 priv->dev = ieee; 161 162 /* 868 MHz BPSK 802.15.4-2003 */ 163 ieee->phy->channels_supported[0] |= 1; 164 /* 915 MHz BPSK 802.15.4-2003 */ 165 ieee->phy->channels_supported[0] |= 0x7fe; 166 /* 2.4 GHz O-QPSK 802.15.4-2003 */ 167 ieee->phy->channels_supported[0] |= 0x7FFF800; 168 /* 868 MHz ASK 802.15.4-2006 */ 169 ieee->phy->channels_supported[1] |= 1; 170 /* 915 MHz ASK 802.15.4-2006 */ 171 ieee->phy->channels_supported[1] |= 0x7fe; 172 /* 868 MHz O-QPSK 802.15.4-2006 */ 173 ieee->phy->channels_supported[2] |= 1; 174 /* 915 MHz O-QPSK 802.15.4-2006 */ 175 ieee->phy->channels_supported[2] |= 0x7fe; 176 /* 2.4 GHz CSS 802.15.4a-2007 */ 177 ieee->phy->channels_supported[3] |= 0x3fff; 178 /* UWB Sub-gigahertz 802.15.4a-2007 */ 179 ieee->phy->channels_supported[4] |= 1; 180 /* UWB Low band 802.15.4a-2007 */ 181 ieee->phy->channels_supported[4] |= 0x1e; 182 /* UWB High band 802.15.4a-2007 */ 183 ieee->phy->channels_supported[4] |= 0xffe0; 184 /* 750 MHz O-QPSK 802.15.4c-2009 */ 185 ieee->phy->channels_supported[5] |= 0xf; 186 /* 750 MHz MPSK 802.15.4c-2009 */ 187 ieee->phy->channels_supported[5] |= 0xf0; 188 /* 950 MHz BPSK 802.15.4d-2009 */ 189 ieee->phy->channels_supported[6] |= 0x3ff; 190 /* 950 MHz GFSK 802.15.4d-2009 */ 191 ieee->phy->channels_supported[6] |= 0x3ffc00; 192 193 INIT_LIST_HEAD(&priv->list); 194 priv->fake = fake; 195 196 spin_lock_init(&priv->lock); 197 198 ieee->parent = dev; 199 200 err = ieee802154_register_device(ieee); 201 if (err) 202 goto err_reg; 203 204 write_lock_bh(&fake->lock); 205 list_add_tail(&priv->list, &fake->list); 206 write_unlock_bh(&fake->lock); 207 208 return 0; 209 210 err_reg: 211 ieee802154_free_device(priv->dev); 212 return err; 213 } 214 215 static void fakelb_del(struct fakelb_dev_priv *priv) 216 { 217 write_lock_bh(&priv->fake->lock); 218 list_del(&priv->list); 219 write_unlock_bh(&priv->fake->lock); 220 221 ieee802154_unregister_device(priv->dev); 222 ieee802154_free_device(priv->dev); 223 } 224 225 static int fakelb_probe(struct platform_device *pdev) 226 { 227 struct fakelb_priv *priv; 228 struct fakelb_dev_priv *dp; 229 int err = -ENOMEM; 230 int i; 231 232 priv = devm_kzalloc(&pdev->dev, sizeof(struct fakelb_priv), 233 GFP_KERNEL); 234 if (!priv) 235 goto err_alloc; 236 237 INIT_LIST_HEAD(&priv->list); 238 rwlock_init(&priv->lock); 239 240 for (i = 0; i < numlbs; i++) { 241 err = fakelb_add_one(&pdev->dev, priv); 242 if (err < 0) 243 goto err_slave; 244 } 245 246 platform_set_drvdata(pdev, priv); 247 dev_info(&pdev->dev, "added ieee802154 hardware\n"); 248 return 0; 249 250 err_slave: 251 list_for_each_entry(dp, &priv->list, list) 252 fakelb_del(dp); 253 err_alloc: 254 return err; 255 } 256 257 static int fakelb_remove(struct platform_device *pdev) 258 { 259 struct fakelb_priv *priv = platform_get_drvdata(pdev); 260 struct fakelb_dev_priv *dp, *temp; 261 262 list_for_each_entry_safe(dp, temp, &priv->list, list) 263 fakelb_del(dp); 264 265 return 0; 266 } 267 268 static struct platform_device *ieee802154fake_dev; 269 270 static struct platform_driver ieee802154fake_driver = { 271 .probe = fakelb_probe, 272 .remove = fakelb_remove, 273 .driver = { 274 .name = "ieee802154fakelb", 275 .owner = THIS_MODULE, 276 }, 277 }; 278 279 static __init int fakelb_init_module(void) 280 { 281 ieee802154fake_dev = platform_device_register_simple( 282 "ieee802154fakelb", -1, NULL, 0); 283 return platform_driver_register(&ieee802154fake_driver); 284 } 285 286 static __exit void fake_remove_module(void) 287 { 288 platform_driver_unregister(&ieee802154fake_driver); 289 platform_device_unregister(ieee802154fake_dev); 290 } 291 292 module_init(fakelb_init_module); 293 module_exit(fake_remove_module); 294 MODULE_LICENSE("GPL"); 295