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/spinlock.h> 30 #include <net/mac802154.h> 31 #include <net/wpan-phy.h> 32 33 static int numlbs = 1; 34 35 struct fakelb_dev_priv { 36 struct ieee802154_dev *dev; 37 38 struct list_head list; 39 struct fakelb_priv *fake; 40 41 spinlock_t lock; 42 bool working; 43 }; 44 45 struct fakelb_priv { 46 struct list_head list; 47 rwlock_t lock; 48 }; 49 50 static int 51 fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level) 52 { 53 might_sleep(); 54 BUG_ON(!level); 55 *level = 0xbe; 56 57 return 0; 58 } 59 60 static int 61 fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel) 62 { 63 pr_debug("set channel to %d\n", channel); 64 65 might_sleep(); 66 dev->phy->current_page = page; 67 dev->phy->current_channel = channel; 68 69 return 0; 70 } 71 72 static void 73 fakelb_hw_deliver(struct fakelb_dev_priv *priv, struct sk_buff *skb) 74 { 75 struct sk_buff *newskb; 76 77 spin_lock(&priv->lock); 78 if (priv->working) { 79 newskb = pskb_copy(skb, GFP_ATOMIC); 80 ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc); 81 } 82 spin_unlock(&priv->lock); 83 } 84 85 static int 86 fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb) 87 { 88 struct fakelb_dev_priv *priv = dev->priv; 89 struct fakelb_priv *fake = priv->fake; 90 91 might_sleep(); 92 93 read_lock_bh(&fake->lock); 94 if (priv->list.next == priv->list.prev) { 95 /* we are the only one device */ 96 fakelb_hw_deliver(priv, skb); 97 } else { 98 struct fakelb_dev_priv *dp; 99 list_for_each_entry(dp, &priv->fake->list, list) { 100 if (dp != priv && 101 (dp->dev->phy->current_channel == 102 priv->dev->phy->current_channel)) 103 fakelb_hw_deliver(dp, skb); 104 } 105 } 106 read_unlock_bh(&fake->lock); 107 108 return 0; 109 } 110 111 static int 112 fakelb_hw_start(struct ieee802154_dev *dev) { 113 struct fakelb_dev_priv *priv = dev->priv; 114 int ret = 0; 115 116 spin_lock(&priv->lock); 117 if (priv->working) 118 ret = -EBUSY; 119 else 120 priv->working = 1; 121 spin_unlock(&priv->lock); 122 123 return ret; 124 } 125 126 static void 127 fakelb_hw_stop(struct ieee802154_dev *dev) { 128 struct fakelb_dev_priv *priv = dev->priv; 129 130 spin_lock(&priv->lock); 131 priv->working = 0; 132 spin_unlock(&priv->lock); 133 } 134 135 static struct ieee802154_ops fakelb_ops = { 136 .owner = THIS_MODULE, 137 .xmit = fakelb_hw_xmit, 138 .ed = fakelb_hw_ed, 139 .set_channel = fakelb_hw_channel, 140 .start = fakelb_hw_start, 141 .stop = fakelb_hw_stop, 142 }; 143 144 /* Number of dummy devices to be set up by this module. */ 145 module_param(numlbs, int, 0); 146 MODULE_PARM_DESC(numlbs, " number of pseudo devices"); 147 148 static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake) 149 { 150 struct fakelb_dev_priv *priv; 151 int err; 152 struct ieee802154_dev *ieee; 153 154 ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops); 155 if (!ieee) 156 return -ENOMEM; 157 158 priv = ieee->priv; 159 priv->dev = ieee; 160 161 /* 868 MHz BPSK 802.15.4-2003 */ 162 ieee->phy->channels_supported[0] |= 1; 163 /* 915 MHz BPSK 802.15.4-2003 */ 164 ieee->phy->channels_supported[0] |= 0x7fe; 165 /* 2.4 GHz O-QPSK 802.15.4-2003 */ 166 ieee->phy->channels_supported[0] |= 0x7FFF800; 167 /* 868 MHz ASK 802.15.4-2006 */ 168 ieee->phy->channels_supported[1] |= 1; 169 /* 915 MHz ASK 802.15.4-2006 */ 170 ieee->phy->channels_supported[1] |= 0x7fe; 171 /* 868 MHz O-QPSK 802.15.4-2006 */ 172 ieee->phy->channels_supported[2] |= 1; 173 /* 915 MHz O-QPSK 802.15.4-2006 */ 174 ieee->phy->channels_supported[2] |= 0x7fe; 175 /* 2.4 GHz CSS 802.15.4a-2007 */ 176 ieee->phy->channels_supported[3] |= 0x3fff; 177 /* UWB Sub-gigahertz 802.15.4a-2007 */ 178 ieee->phy->channels_supported[4] |= 1; 179 /* UWB Low band 802.15.4a-2007 */ 180 ieee->phy->channels_supported[4] |= 0x1e; 181 /* UWB High band 802.15.4a-2007 */ 182 ieee->phy->channels_supported[4] |= 0xffe0; 183 /* 750 MHz O-QPSK 802.15.4c-2009 */ 184 ieee->phy->channels_supported[5] |= 0xf; 185 /* 750 MHz MPSK 802.15.4c-2009 */ 186 ieee->phy->channels_supported[5] |= 0xf0; 187 /* 950 MHz BPSK 802.15.4d-2009 */ 188 ieee->phy->channels_supported[6] |= 0x3ff; 189 /* 950 MHz GFSK 802.15.4d-2009 */ 190 ieee->phy->channels_supported[6] |= 0x3ffc00; 191 192 INIT_LIST_HEAD(&priv->list); 193 priv->fake = fake; 194 195 spin_lock_init(&priv->lock); 196 197 ieee->parent = dev; 198 199 err = ieee802154_register_device(ieee); 200 if (err) 201 goto err_reg; 202 203 write_lock_bh(&fake->lock); 204 list_add_tail(&priv->list, &fake->list); 205 write_unlock_bh(&fake->lock); 206 207 return 0; 208 209 err_reg: 210 ieee802154_free_device(priv->dev); 211 return err; 212 } 213 214 static void fakelb_del(struct fakelb_dev_priv *priv) 215 { 216 write_lock_bh(&priv->fake->lock); 217 list_del(&priv->list); 218 write_unlock_bh(&priv->fake->lock); 219 220 ieee802154_unregister_device(priv->dev); 221 ieee802154_free_device(priv->dev); 222 } 223 224 static int fakelb_probe(struct platform_device *pdev) 225 { 226 struct fakelb_priv *priv; 227 struct fakelb_dev_priv *dp; 228 int err = -ENOMEM; 229 int i; 230 231 priv = kzalloc(sizeof(struct fakelb_priv), GFP_KERNEL); 232 if (!priv) 233 goto err_alloc; 234 235 INIT_LIST_HEAD(&priv->list); 236 rwlock_init(&priv->lock); 237 238 for (i = 0; i < numlbs; i++) { 239 err = fakelb_add_one(&pdev->dev, priv); 240 if (err < 0) 241 goto err_slave; 242 } 243 244 platform_set_drvdata(pdev, priv); 245 dev_info(&pdev->dev, "added ieee802154 hardware\n"); 246 return 0; 247 248 err_slave: 249 list_for_each_entry(dp, &priv->list, list) 250 fakelb_del(dp); 251 kfree(priv); 252 err_alloc: 253 return err; 254 } 255 256 static int fakelb_remove(struct platform_device *pdev) 257 { 258 struct fakelb_priv *priv = platform_get_drvdata(pdev); 259 struct fakelb_dev_priv *dp, *temp; 260 261 list_for_each_entry_safe(dp, temp, &priv->list, list) 262 fakelb_del(dp); 263 kfree(priv); 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