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