1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/netdevice.h>
26#include <linux/skbuff.h>
27#include <linux/if_arp.h>
28
29#include <net/af_ieee802154.h>
30#include <net/ieee802154_netdev.h>
31#include <net/ieee802154.h>
32#include <net/nl802154.h>
33#include <net/wpan-phy.h>
34
35struct wpan_phy *net_to_phy(struct net_device *dev)
36{
37 return container_of(dev->dev.parent, struct wpan_phy, dev);
38}
39
40
41
42
43
44
45
46static u16 fake_get_pan_id(struct net_device *dev)
47{
48 BUG_ON(dev->type != ARPHRD_IEEE802154);
49
50 return 0xeba1;
51}
52
53
54
55
56
57
58
59
60
61static u16 fake_get_short_addr(struct net_device *dev)
62{
63 BUG_ON(dev->type != ARPHRD_IEEE802154);
64
65 return 0x1;
66}
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81static u8 fake_get_dsn(struct net_device *dev)
82{
83 BUG_ON(dev->type != ARPHRD_IEEE802154);
84
85 return 0x00;
86}
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101static u8 fake_get_bsn(struct net_device *dev)
102{
103 BUG_ON(dev->type != ARPHRD_IEEE802154);
104
105 return 0x00;
106}
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121static int fake_assoc_req(struct net_device *dev,
122 struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
123{
124 struct wpan_phy *phy = net_to_phy(dev);
125
126 mutex_lock(&phy->pib_lock);
127 phy->current_channel = channel;
128 phy->current_page = page;
129 mutex_unlock(&phy->pib_lock);
130
131
132 return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev),
133 IEEE802154_SUCCESS);
134}
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151static int fake_assoc_resp(struct net_device *dev,
152 struct ieee802154_addr *addr, u16 short_addr, u8 status)
153{
154 return 0;
155}
156
157
158
159
160
161
162
163
164
165
166
167
168
169static int fake_disassoc_req(struct net_device *dev,
170 struct ieee802154_addr *addr, u8 reason)
171{
172 return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
173}
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr,
195 u8 channel, u8 page,
196 u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
197 u8 coord_realign)
198{
199 struct wpan_phy *phy = net_to_phy(dev);
200
201 mutex_lock(&phy->pib_lock);
202 phy->current_channel = channel;
203 phy->current_page = page;
204 mutex_unlock(&phy->pib_lock);
205
206
207 ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER);
208 return 0;
209}
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
227 u8 page, u8 duration)
228{
229 u8 edl[27] = {};
230 return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type,
231 channels, page,
232 type == IEEE802154_MAC_SCAN_ED ? edl : NULL);
233}
234
235static struct ieee802154_mlme_ops fake_mlme = {
236 .assoc_req = fake_assoc_req,
237 .assoc_resp = fake_assoc_resp,
238 .disassoc_req = fake_disassoc_req,
239 .start_req = fake_start_req,
240 .scan_req = fake_scan_req,
241
242 .get_pan_id = fake_get_pan_id,
243 .get_short_addr = fake_get_short_addr,
244 .get_dsn = fake_get_dsn,
245 .get_bsn = fake_get_bsn,
246};
247
248static int ieee802154_fake_open(struct net_device *dev)
249{
250 netif_start_queue(dev);
251 return 0;
252}
253
254static int ieee802154_fake_close(struct net_device *dev)
255{
256 netif_stop_queue(dev);
257 return 0;
258}
259
260static netdev_tx_t ieee802154_fake_xmit(struct sk_buff *skb,
261 struct net_device *dev)
262{
263 dev->stats.tx_packets++;
264 dev->stats.tx_bytes += skb->len;
265
266
267
268 dev_kfree_skb(skb);
269 return NETDEV_TX_OK;
270}
271
272
273static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr,
274 int cmd)
275{
276 struct sockaddr_ieee802154 *sa =
277 (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
278 u16 pan_id, short_addr;
279
280 switch (cmd) {
281 case SIOCGIFADDR:
282
283 pan_id = fake_get_pan_id(dev);
284 short_addr = fake_get_short_addr(dev);
285 if (pan_id == IEEE802154_PANID_BROADCAST ||
286 short_addr == IEEE802154_ADDR_BROADCAST)
287 return -EADDRNOTAVAIL;
288
289 sa->family = AF_IEEE802154;
290 sa->addr.addr_type = IEEE802154_ADDR_SHORT;
291 sa->addr.pan_id = pan_id;
292 sa->addr.short_addr = short_addr;
293 return 0;
294 }
295 return -ENOIOCTLCMD;
296}
297
298static int ieee802154_fake_mac_addr(struct net_device *dev, void *p)
299{
300 return -EBUSY;
301}
302
303static const struct net_device_ops fake_ops = {
304 .ndo_open = ieee802154_fake_open,
305 .ndo_stop = ieee802154_fake_close,
306 .ndo_start_xmit = ieee802154_fake_xmit,
307 .ndo_do_ioctl = ieee802154_fake_ioctl,
308 .ndo_set_mac_address = ieee802154_fake_mac_addr,
309};
310
311static void ieee802154_fake_destruct(struct net_device *dev)
312{
313 struct wpan_phy *phy = net_to_phy(dev);
314
315 wpan_phy_unregister(phy);
316 free_netdev(dev);
317 wpan_phy_free(phy);
318}
319
320static void ieee802154_fake_setup(struct net_device *dev)
321{
322 dev->addr_len = IEEE802154_ADDR_LEN;
323 memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
324 dev->features = NETIF_F_NO_CSUM;
325 dev->needed_tailroom = 2;
326 dev->mtu = 127;
327 dev->tx_queue_len = 10;
328 dev->type = ARPHRD_IEEE802154;
329 dev->flags = IFF_NOARP | IFF_BROADCAST;
330 dev->watchdog_timeo = 0;
331 dev->destructor = ieee802154_fake_destruct;
332}
333
334
335static int __devinit ieee802154fake_probe(struct platform_device *pdev)
336{
337 struct net_device *dev;
338 struct wpan_phy *phy = wpan_phy_alloc(0);
339 int err;
340
341 if (!phy)
342 return -ENOMEM;
343
344 dev = alloc_netdev(0, "hardwpan%d", ieee802154_fake_setup);
345 if (!dev) {
346 wpan_phy_free(phy);
347 return -ENOMEM;
348 }
349
350 phy->dev.platform_data = dev;
351
352 memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
353 dev->addr_len);
354 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
355
356 phy->channels_supported = (1 << 27) - 1;
357 phy->transmit_power = 0xbf;
358
359 dev->netdev_ops = &fake_ops;
360 dev->ml_priv = &fake_mlme;
361
362
363
364
365
366 if (strchr(dev->name, '%')) {
367 err = dev_alloc_name(dev, dev->name);
368 if (err < 0)
369 goto out;
370 }
371
372 SET_NETDEV_DEV(dev, &phy->dev);
373
374 platform_set_drvdata(pdev, dev);
375
376 err = wpan_phy_register(&pdev->dev, phy);
377 if (err)
378 goto out;
379
380 err = register_netdev(dev);
381 if (err < 0)
382 goto out;
383
384 dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
385 return 0;
386
387out:
388 unregister_netdev(dev);
389 return err;
390}
391
392static int __devexit ieee802154fake_remove(struct platform_device *pdev)
393{
394 struct net_device *dev = platform_get_drvdata(pdev);
395 unregister_netdev(dev);
396 return 0;
397}
398
399static struct platform_device *ieee802154fake_dev;
400
401static struct platform_driver ieee802154fake_driver = {
402 .probe = ieee802154fake_probe,
403 .remove = __devexit_p(ieee802154fake_remove),
404 .driver = {
405 .name = "ieee802154hardmac",
406 .owner = THIS_MODULE,
407 },
408};
409
410static __init int fake_init(void)
411{
412 ieee802154fake_dev = platform_device_register_simple(
413 "ieee802154hardmac", -1, NULL, 0);
414 return platform_driver_register(&ieee802154fake_driver);
415}
416
417static __exit void fake_exit(void)
418{
419 platform_driver_unregister(&ieee802154fake_driver);
420 platform_device_unregister(ieee802154fake_dev);
421}
422
423module_init(fake_init);
424module_exit(fake_exit);
425MODULE_LICENSE("GPL");
426
427