Date:2012-06-08 04:49:34 (11 years 9 months ago)
Author:Xiangfu
Commit:363808284926888d09095a2950f535a60cb37afb
Message:xburst: add WPAN support

Files: target/linux/xburst/patches-3.3/800-WPAN-new-files.patch (1 diff)
target/linux/xburst/patches-3.3/800-WPAN-patches.patch (1 diff)

Change Details

target/linux/xburst/patches-3.3/800-WPAN-new-files.patch
1From 6d184ce0928a5a30e88e3e4b7be4200aa103abc3 Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Tue, 5 Jun 2012 11:32:52 +0800
4Subject: [PATCH 2/3] 001
5
6---
7 drivers/ieee802154/adf7242.c | 1034 +++++++++++++++++++++++++++++++++++++++
8 drivers/ieee802154/at86rf230.c | 872 +++++++++++++++++++++++++++++++++
9 drivers/ieee802154/at86rf230.h | 211 ++++++++
10 drivers/ieee802154/cc2420.c | 859 ++++++++++++++++++++++++++++++++
11 drivers/ieee802154/fakelb.c | 311 ++++++++++++
12 drivers/ieee802154/serial.c | 1047 ++++++++++++++++++++++++++++++++++++++++
13 drivers/ieee802154/spi_atben.c | 421 ++++++++++++++++
14 drivers/ieee802154/spi_atusb.c | 750 ++++++++++++++++++++++++++++
15 include/linux/if_ieee802154.h | 6 +
16 include/linux/spi/at86rf230.h | 34 ++
17 include/net/mac802154.h | 156 ++++++
18 net/mac802154/Kconfig | 24 +
19 net/mac802154/Makefile | 6 +
20 net/mac802154/beacon.c | 285 +++++++++++
21 net/mac802154/beacon_hash.c | 106 ++++
22 net/mac802154/beacon_hash.h | 41 ++
23 net/mac802154/mac802154.h | 126 +++++
24 net/mac802154/mac_cmd.c | 365 ++++++++++++++
25 net/mac802154/main.c | 283 +++++++++++
26 net/mac802154/mib.c | 249 ++++++++++
27 net/mac802154/mib.h | 35 ++
28 net/mac802154/monitor.c | 117 +++++
29 net/mac802154/rx.c | 117 +++++
30 net/mac802154/scan.c | 203 ++++++++
31 net/mac802154/smac.c | 128 +++++
32 net/mac802154/tx.c | 106 ++++
33 net/mac802154/wpan.c | 631 ++++++++++++++++++++++++
34 net/zigbee/Kconfig | 7 +
35 net/zigbee/Makefile | 5 +
36 net/zigbee/af_zigbee.c | 285 +++++++++++
37 net/zigbee/dgram.c | 401 +++++++++++++++
38 31 files changed, 9221 insertions(+), 0 deletions(-)
39 create mode 100644 drivers/ieee802154/adf7242.c
40 create mode 100644 drivers/ieee802154/at86rf230.c
41 create mode 100644 drivers/ieee802154/at86rf230.h
42 create mode 100644 drivers/ieee802154/cc2420.c
43 create mode 100644 drivers/ieee802154/fakelb.c
44 create mode 100644 drivers/ieee802154/serial.c
45 create mode 100644 drivers/ieee802154/spi_atben.c
46 create mode 100644 drivers/ieee802154/spi_atusb.c
47 create mode 100644 include/linux/if_ieee802154.h
48 create mode 100644 include/linux/spi/at86rf230.h
49 create mode 100644 include/net/mac802154.h
50 create mode 100644 net/mac802154/Kconfig
51 create mode 100644 net/mac802154/Makefile
52 create mode 100644 net/mac802154/beacon.c
53 create mode 100644 net/mac802154/beacon_hash.c
54 create mode 100644 net/mac802154/beacon_hash.h
55 create mode 100644 net/mac802154/mac802154.h
56 create mode 100644 net/mac802154/mac_cmd.c
57 create mode 100644 net/mac802154/main.c
58 create mode 100644 net/mac802154/mib.c
59 create mode 100644 net/mac802154/mib.h
60 create mode 100644 net/mac802154/monitor.c
61 create mode 100644 net/mac802154/rx.c
62 create mode 100644 net/mac802154/scan.c
63 create mode 100644 net/mac802154/smac.c
64 create mode 100644 net/mac802154/tx.c
65 create mode 100644 net/mac802154/wpan.c
66 create mode 100644 net/zigbee/Kconfig
67 create mode 100644 net/zigbee/Makefile
68 create mode 100644 net/zigbee/af_zigbee.c
69 create mode 100644 net/zigbee/dgram.c
70
71diff --git a/drivers/ieee802154/adf7242.c b/drivers/ieee802154/adf7242.c
72new file mode 100644
73index 0000000..b578a55
74--- /dev/null
75@@ -0,0 +1,1034 @@
76+/*
77+ * Analog Devices ADF7242 Low-Power IEEE 802.15.4 Transceiver
78+ *
79+ * Copyright 2009-2010 Analog Devices Inc.
80+ *
81+ * Licensed under the GPL-2 or later.
82+ */
83+
84+#include <linux/kernel.h>
85+#include <linux/module.h>
86+#include <linux/interrupt.h>
87+#include <linux/delay.h>
88+#include <linux/mutex.h>
89+#include <linux/workqueue.h>
90+#include <linux/spinlock.h>
91+#include <linux/firmware.h>
92+#include <linux/spi/spi.h>
93+#include <linux/spi/adf7242.h>
94+
95+#include <net/mac802154.h>
96+#include <net/wpan-phy.h>
97+
98+/*
99+ * DEBUG LEVEL
100+ * 0 OFF
101+ * 1 INFO
102+ * 2 INFO + TRACE
103+ */
104+
105+#define ADF_DEBUG 0
106+#define DBG(n, args...) do { if (ADF_DEBUG >= (n)) pr_debug(args); } while (0)
107+
108+#define FIRMWARE "adf7242_firmware.bin"
109+#define MAX_POLL_LOOPS 10
110+
111+/* All Registers */
112+
113+#define REG_EXT_CTRL 0x100 /* RW External LNA/PA and internal PA control configuration bits */
114+#define REG_TX_FSK_TEST 0x101 /* RW TX FSK test mode configuration */
115+#define REG_CCA1 0x105 /* RW RSSI threshold for CCA */
116+#define REG_CCA2 0x106 /* RW CCA mode configuration */
117+#define REG_BUFFERCFG 0x107 /* RW RX_BUFFER overwrite control */
118+#define REG_PKT_CFG 0x108 /* RW FCS evaluation configuration */
119+#define REG_DELAYCFG0 0x109 /* RW RC_RX command to SFD or sync word search delay */
120+#define REG_DELAYCFG1 0x10A /* RW RC_TX command to TX state */
121+#define REG_DELAYCFG2 0x10B /* RW Mac delay extention */
122+#define REG_SYNC_WORD0 0x10C /* RW sync word bits [7:0] of [23:0] */
123+#define REG_SYNC_WORD1 0x10D /* RW sync word bits [15:8] of [23:0] */
124+#define REG_SYNC_WORD2 0x10E /* RW sync word bits [23:16] of [23:0] */
125+#define REG_SYNC_CONFIG 0x10F /* RW sync word configuration */
126+#define REG_RC_CFG 0x13E /* RW RX / TX packet configuration */
127+#define REG_RC_VAR44 0x13F /* RW RESERVED */
128+#define REG_CH_FREQ0 0x300 /* RW Channel Frequency Settings - Low Byte */
129+#define REG_CH_FREQ1 0x301 /* RW Channel Frequency Settings - Middle Byte */
130+#define REG_CH_FREQ2 0x302 /* RW Channel Frequency Settings - 2 MSBs */
131+#define REG_TX_FD 0x304 /* RW TX Frequency Deviation Register */
132+#define REG_DM_CFG0 0x305 /* RW RX Discriminator BW Register */
133+#define REG_TX_M 0x306 /* RW TX Mode Register */
134+#define REG_RX_M 0x307 /* RW RX Mode Register */
135+#define REG_RRB 0x30C /* R RSSI Readback Register */
136+#define REG_LRB 0x30D /* R Link Quality Readback Register */
137+#define REG_DR0 0x30E /* RW bits [15:8] of [15:0] for data rate setting */
138+#define REG_DR1 0x30F /* RW bits [7:0] of [15:0] for data rate setting */
139+#define REG_PRAMPG 0x313 /* RW RESERVED */
140+#define REG_TXPB 0x314 /* RW TX Packet Storage Base Address */
141+#define REG_RXPB 0x315 /* RW RX Packet Storage Base Address */
142+#define REG_TMR_CFG0 0x316 /* RW Wake up Timer Configuration Register - High Byte */
143+#define REG_TMR_CFG1 0x317 /* RW Wake up Timer Configuration Register - Low Byte */
144+#define REG_TMR_RLD0 0x318 /* RW Wake up Timer Value Register - High Byte */
145+#define REG_TMR_RLD1 0x319 /* RW Wake up Timer Value Register - Low Byte */
146+#define REG_TMR_CTRL 0x31A /* RW Wake up Timer Timeout flag */
147+#define REG_PD_AUX 0x31E /* RW Battmon enable */
148+#define REG_GP_CFG 0x32C /* RW GPIO Configuration */
149+#define REG_GP_OUT 0x32D /* RW GPIO Configuration */
150+#define REG_GP_IN 0x32E /* R GPIO Configuration */
151+#define REG_SYNT 0x335 /* RW bandwidth calibration timers */
152+#define REG_CAL_CFG 0x33D /* RW Calibration Settings */
153+#define REG_SYNT_CAL 0x371 /* RW Oscillator and Doubler Configuration */
154+#define REG_IIRF_CFG 0x389 /* RW BB Filter Decimation Rate */
155+#define REG_CDR_CFG 0x38A /* RW CDR kVCO */
156+#define REG_DM_CFG1 0x38B /* RW Postdemodulator Filter */
157+#define REG_AGCSTAT 0x38E /* R RXBB Ref Osc Calibration Engine Readback */
158+#define REG_RXCAL0 0x395 /* RW RX BB filter tuning, LSB */
159+#define REG_RXCAL1 0x396 /* RW RX BB filter tuning, MSB */
160+#define REG_RXFE_CFG 0x39B /* RW RXBB Ref Osc & RXFE Calibration */
161+#define REG_PA_RR 0x3A7 /* RW Set PA ramp rate */
162+#define REG_PA_CFG 0x3A8 /* RW PA enable */
163+#define REG_EXTPA_CFG 0x3A9 /* RW External PA BIAS DAC */
164+#define REG_EXTPA_MSC 0x3AA /* RW PA Bias Mode */
165+#define REG_ADC_RBK 0x3AE /* R Readback temp */
166+#define REG_AGC_CFG1 0x3B2 /* RW GC Parameters */
167+#define REG_AGC_MAX 0x3B4 /* RW Slew rate */
168+#define REG_AGC_CFG2 0x3B6 /* RW RSSI Parameters */
169+#define REG_AGC_CFG3 0x3B7 /* RW RSSI Parameters */
170+#define REG_AGC_CFG4 0x3B8 /* RW RSSI Parameters */
171+#define REG_AGC_CFG5 0x3B9 /* RW RSSI & NDEC Parameters */
172+#define REG_AGC_CFG6 0x3BA /* RW NDEC Parameters */
173+#define REG_OCL_CFG1 0x3C4 /* RW OCL System Parameters */
174+#define REG_IRQ1_EN0 0x3C7 /* RW Interrupt Mask set bits [7:0] of [15:0] for IRQ1 */
175+#define REG_IRQ1_EN1 0x3C8 /* RW Interrupt Mask set bits [15:8] of [15:0] for IRQ1 */
176+#define REG_IRQ2_EN0 0x3C9 /* RW Interrupt Mask set bits [7:0] of [15:0] for IRQ2 */
177+#define REG_IRQ2_EN1 0x3CA /* RW Interrupt Mask set bits [15:8] of [15:0] for IRQ2 */
178+#define REG_IRQ1_SRC0 0x3CB /* RW Interrupt Source bits [7:0] of [15:0] for IRQ */
179+#define REG_IRQ1_SRC1 0x3CC /* RW Interrupt Source bits [15:8] of [15:0] for IRQ */
180+#define REG_OCL_BW0 0x3D2 /* RW OCL System Parameters */
181+#define REG_OCL_BW1 0x3D3 /* RW OCL System Parameters */
182+#define REG_OCL_BW2 0x3D4 /* RW OCL System Parameters */
183+#define REG_OCL_BW3 0x3D5 /* RW OCL System Parameters */
184+#define REG_OCL_BW4 0x3D6 /* RW OCL System Parameters */
185+#define REG_OCL_BWS 0x3D7 /* RW OCL System Parameters */
186+#define REG_OCL_CFG13 0x3E0 /* RW OCL System Parameters */
187+#define REG_GP_DRV 0x3E3 /* RW I/O pads Configuration and bg trim */
188+#define REG_BM_CFG 0x3E6 /* RW Battery Monitor Threshold Voltage setting */
189+#define REG_SFD_15_4 0x3F4 /* RW Option to set non standard SFD */
190+#define REG_AFC_CFG 0x3F7 /* RW AFC mode and polarity */
191+#define REG_AFC_KI_KP 0x3F8 /* RW AFC ki and kp */
192+#define REG_AFC_RANGE 0x3F9 /* RW AFC range */
193+#define REG_AFC_READ 0x3FA /* RW Readback frequency error */
194+
195+#define REG_PAN_ID0 0x112
196+#define REG_PAN_ID1 0x113
197+#define REG_SHORT_ADDR_0 0x114
198+#define REG_SHORT_ADDR_1 0x115
199+#define REG_IEEE_ADDR_0 0x116
200+#define REG_IEEE_ADDR_1 0x117
201+#define REG_IEEE_ADDR_2 0x118
202+#define REG_IEEE_ADDR_3 0x119
203+#define REG_IEEE_ADDR_4 0x11A
204+#define REG_IEEE_ADDR_5 0x11B
205+#define REG_IEEE_ADDR_6 0x11C
206+#define REG_IEEE_ADDR_7 0x11D
207+#define REG_FFILT_CFG 0x11E
208+#define REG_AUTO_CFG 0x11F
209+#define REG_AUTO_TX1 0x120
210+#define REG_AUTO_TX2 0x121
211+#define REG_AUTO_STATUS 0x122
212+
213+/* REG_FFILT_CFG */
214+#define ACCEPT_BEACON_FRAMES (1 << 0)
215+#define ACCEPT_DATA_FRAMES (1 << 1)
216+#define ACCEPT_ACK_FRAMES (1 << 2)
217+#define ACCEPT_MACCMD_FRAMES (1 << 3)
218+#define ACCEPT_RESERVED_FRAMES (1 << 4)
219+#define ACCEPT_ALL_ADDRESS (1 << 5)
220+
221+/* REG_AUTO_CFG */
222+#define AUTO_ACK_FRAMEPEND (1 << 0)
223+#define IS_PANCOORD (1 << 1)
224+#define RX_AUTO_ACK_EN (1 << 3)
225+#define CSMA_CA_RX_TURNAROUND (1 << 4)
226+
227+/* REG_AUTO_TX1 */
228+#define MAX_FRAME_RETRIES(x) ((x) & 0xF)
229+#define MAX_CCA_RETRIES(x) (((x) & 0x7) << 4)
230+
231+/* REG_AUTO_TX2 */
232+#define CSMA_MAX_BE(x) ((x) & 0xF)
233+#define CSMA_MIN_BE(x) (((x) & 0xF) << 4)
234+
235+#define CMD_SPI_NOP 0xFF /* No operation. Use for dummy writes */
236+#define CMD_SPI_PKT_WR 0x10 /* Write telegram to the Packet RAM starting from the TX packet base address pointer tx_packet_base */
237+#define CMD_SPI_PKT_RD 0x30 /* Read telegram from the Packet RAM starting from RX packet base address pointer rxpb.rx_packet_base */
238+#define CMD_SPI_MEM_WR(x) (0x18 + (x >> 8)) /* Write data to MCR or Packet RAM sequentially */
239+#define CMD_SPI_MEM_RD(x) (0x38 + (x >> 8)) /* Read data from MCR or Packet RAM sequentially */
240+#define CMD_SPI_MEMR_WR(x) (0x08 + (x >> 8)) /* Write data to MCR or Packet RAM as random block */
241+#define CMD_SPI_MEMR_RD(x) (0x28 + (x >> 8)) /* Read data from MCR or Packet RAM as random block */
242+#define CMD_SPI_PRAM_WR 0x1E /* Write data sequentially to current PRAM page selected */
243+#define CMD_RC_SLEEP 0xB1 /* Invoke transition of radio controller into SLEEP state */
244+#define CMD_RC_IDLE 0xB2 /* Invoke transition of radio controller into IDLE state */
245+#define CMD_RC_PHY_RDY 0xB3 /* Invoke transition of radio controller into PHY_RDY state */
246+#define CMD_RC_RX 0xB4 /* Invoke transition of radio controller into RX state */
247+#define CMD_RC_TX 0xB5 /* Invoke transition of radio controller into TX state */
248+#define CMD_RC_MEAS 0xB6 /* Invoke transition of radio controller into MEAS state */
249+#define CMD_RC_CCA 0xB7 /* Invoke Clear channel assessment */
250+#define CMD_RC_CSMACA 0xC1 /* initiates CSMA-CA channel access sequence and frame transmission */
251+
252+/* STATUS */
253+
254+#define STAT_SPI_READY (1 << 7)
255+#define STAT_IRQ_STATUS (1 << 6)
256+#define STAT_RC_READY (1 << 5)
257+#define STAT_CCA_RESULT (1 << 4)
258+#define RC_STATUS_IDLE 1
259+#define RC_STATUS_MEAS 2
260+#define RC_STATUS_PHY_RDY 3
261+#define RC_STATUS_RX 4
262+#define RC_STATUS_TX 5
263+#define RC_STATUS_MASK 0xF
264+
265+/* AUTO_STATUS */
266+
267+#define SUCCESS 0
268+#define SUCCESS_DATPEND 1
269+#define FAILURE_CSMACA 2
270+#define FAILURE_NOACK 3
271+#define AUTO_STATUS_MASK 0x3
272+
273+#define PRAM_PAGESIZE 256
274+
275+/* IRQ1 */
276+
277+#define IRQ_CCA_COMPLETE (1 << 0)
278+#define IRQ_SFD_RX (1 << 1)
279+#define IRQ_SFD_TX (1 << 2)
280+#define IRQ_RX_PKT_RCVD (1 << 3)
281+#define IRQ_TX_PKT_SENT (1 << 4)
282+#define IRQ_FRAME_VALID (1 << 5)
283+#define IRQ_ADDRESS_VALID (1 << 6)
284+#define IRQ_CSMA_CA (1 << 7)
285+
286+#define AUTO_TX_TURNAROUND (1 << 3)
287+#define ADDON_EN (1 << 4)
288+
289+struct adf7242_local {
290+ struct spi_device *spi;
291+ struct adf7242_platform_data *pdata;
292+ struct work_struct irqwork;
293+ struct completion tx_complete;
294+ struct ieee802154_dev *dev;
295+ struct mutex bmux;
296+ spinlock_t lock;
297+ unsigned irq_disabled:1; /* P: lock */
298+ unsigned is_tx:1; /* P: lock */
299+ unsigned mode;
300+ unsigned tx_irq;
301+ int tx_stat;
302+ u8 buf[3];
303+};
304+
305+static int adf7242_status(struct adf7242_local *lp, u8 *stat)
306+{
307+ int status;
308+ struct spi_message msg;
309+ u8 buf_tx[1], buf_rx[1];
310+
311+ struct spi_transfer xfer = {
312+ .len = 1,
313+ .tx_buf = buf_tx,
314+ .rx_buf = buf_rx,
315+ };
316+
317+ buf_tx[0] = CMD_SPI_NOP;
318+
319+ spi_message_init(&msg);
320+ spi_message_add_tail(&xfer, &msg);
321+
322+ mutex_lock(&lp->bmux);
323+ status = spi_sync(lp->spi, &msg);
324+ mutex_unlock(&lp->bmux);
325+
326+ *stat = buf_rx[0];
327+
328+ return status;
329+}
330+
331+static int adf7242_wait_ready(struct adf7242_local *lp)
332+{
333+ u8 stat;
334+ int cnt = 0;
335+
336+ DBG(2, "%s :Enter\n", __func__);
337+
338+ do {
339+ adf7242_status(lp, &stat);
340+ cnt++;
341+ } while (!(stat & STAT_RC_READY) && (cnt < MAX_POLL_LOOPS));
342+
343+ DBG(2, "%s :Exit loops=%d\n", __func__, cnt);
344+
345+ return 0;
346+}
347+
348+static int adf7242_wait_status(struct adf7242_local *lp, int status)
349+{
350+ u8 stat;
351+ int cnt = 0;
352+
353+ DBG(2, "%s :Enter\n", __func__);
354+
355+ do {
356+ adf7242_status(lp, &stat);
357+ stat &= RC_STATUS_MASK;
358+ cnt++;
359+ } while ((stat != status) && (cnt < MAX_POLL_LOOPS));
360+
361+ DBG(2, "%s :Exit loops=%d\n", __func__, cnt);
362+
363+ return 0;
364+}
365+
366+static int adf7242_write_fbuf(struct adf7242_local *lp, u8 *data, u8 len)
367+{
368+ u8 *buf = lp->buf;
369+ int status;
370+ struct spi_message msg;
371+ struct spi_transfer xfer_head = {
372+ .len = 2,
373+ .tx_buf = buf,
374+
375+ };
376+ struct spi_transfer xfer_buf = {
377+ .len = len,
378+ .tx_buf = data,
379+ };
380+
381+ DBG(2, "%s :Enter\n", __func__);
382+ adf7242_wait_ready(lp);
383+
384+ buf[0] = CMD_SPI_PKT_WR;
385+ buf[1] = len + 2;
386+
387+ spi_message_init(&msg);
388+ spi_message_add_tail(&xfer_head, &msg);
389+ spi_message_add_tail(&xfer_buf, &msg);
390+
391+ mutex_lock(&lp->bmux);
392+ status = spi_sync(lp->spi, &msg);
393+ mutex_unlock(&lp->bmux);
394+
395+ DBG(2, "%s :Exit\n", __func__);
396+ return status;
397+}
398+
399+static int adf7242_read_fbuf(struct adf7242_local *lp,
400+ u8 *data, u8 *len, u8 *lqi)
401+{
402+ u8 *buf = lp->buf;
403+ int status;
404+ struct spi_message msg;
405+ struct spi_transfer xfer_head = {
406+ .len = 3,
407+ .tx_buf = buf,
408+ .rx_buf = buf,
409+
410+ };
411+ struct spi_transfer xfer_buf = {
412+ .len = *len,
413+ .rx_buf = data,
414+ };
415+
416+ DBG(2, "%s :Enter\n", __func__);
417+ adf7242_wait_ready(lp);
418+
419+ mutex_lock(&lp->bmux);
420+ buf[0] = CMD_SPI_PKT_RD;
421+ buf[1] = CMD_SPI_NOP;
422+ buf[2] = 0; /* PHR */
423+
424+ spi_message_init(&msg);
425+ spi_message_add_tail(&xfer_head, &msg);
426+ spi_message_add_tail(&xfer_buf, &msg);
427+
428+ status = spi_sync(lp->spi, &msg);
429+
430+ if (!status) {
431+ *lqi = data[buf[2] - 1];
432+ *len = buf[2]; /* PHR */
433+ }
434+
435+ mutex_unlock(&lp->bmux);
436+ DBG(2, "%s :Exit\n", __func__);
437+ return status;
438+}
439+
440+static int adf7242_read_reg(struct adf7242_local *lp,
441+ u16 addr, u8 *data)
442+{
443+ int status;
444+ struct spi_message msg;
445+ u8 buf_tx[4], buf_rx[4];
446+
447+ struct spi_transfer xfer = {
448+ .len = 4,
449+ .tx_buf = buf_tx,
450+ .rx_buf = buf_rx,
451+ };
452+
453+ DBG(2, "%s :Enter\n", __func__);
454+ adf7242_wait_ready(lp);
455+
456+ mutex_lock(&lp->bmux);
457+ buf_tx[0] = CMD_SPI_MEM_RD(addr);
458+ buf_tx[1] = addr;
459+ buf_tx[2] = CMD_SPI_NOP;
460+ buf_tx[3] = CMD_SPI_NOP;
461+
462+ spi_message_init(&msg);
463+ spi_message_add_tail(&xfer, &msg);
464+
465+ status = spi_sync(lp->spi, &msg);
466+ if (msg.status)
467+ status = msg.status;
468+
469+ if (!status)
470+ *data = buf_rx[3];
471+
472+ mutex_unlock(&lp->bmux);
473+ DBG(2, "%s :Exit\n", __func__);
474+
475+ return status;
476+}
477+
478+static int adf7242_write_reg(struct adf7242_local *lp,
479+ u16 addr, u8 data)
480+{
481+ int status;
482+ struct spi_message msg;
483+ u8 buf_tx[4];
484+
485+ struct spi_transfer xfer = {
486+ .len = 3,
487+ .tx_buf = buf_tx,
488+ };
489+ DBG(2, "%s :Enter\n", __func__);
490+ adf7242_wait_ready(lp);
491+
492+ buf_tx[0] = CMD_SPI_MEM_WR(addr);
493+ buf_tx[1] = addr;
494+ buf_tx[2] = data;
495+
496+ spi_message_init(&msg);
497+ spi_message_add_tail(&xfer, &msg);
498+
499+ mutex_lock(&lp->bmux);
500+ status = spi_sync(lp->spi, &msg);
501+ mutex_unlock(&lp->bmux);
502+ DBG(2, "%s :Exit\n", __func__);
503+
504+ return status;
505+}
506+
507+static int adf7242_cmd(struct adf7242_local *lp, u8 cmd)
508+{
509+ int status;
510+ struct spi_message msg;
511+ u8 buf_tx[1];
512+
513+ struct spi_transfer xfer = {
514+ .len = 1,
515+ .tx_buf = buf_tx,
516+ };
517+
518+ DBG(2, "%s :Enter CMD=0x%X\n", __func__, cmd);
519+ adf7242_wait_ready(lp);
520+
521+ buf_tx[0] = cmd;
522+ spi_message_init(&msg);
523+ spi_message_add_tail(&xfer, &msg);
524+
525+ mutex_lock(&lp->bmux);
526+ status = spi_sync(lp->spi, &msg);
527+ mutex_unlock(&lp->bmux);
528+ DBG(2, "%s :Exit\n", __func__);
529+
530+ return status;
531+}
532+
533+static int adf7242_upload_firmware(struct adf7242_local *lp,
534+ u8 *data, u16 len)
535+{
536+ int status, i, page = 0;
537+ struct spi_message msg;
538+ struct spi_transfer xfer_buf = {};
539+ u8 buf[2];
540+
541+ struct spi_transfer xfer_head = {
542+ .len = 2,
543+ .tx_buf = buf,
544+ };
545+
546+ buf[0] = CMD_SPI_PRAM_WR;
547+ buf[1] = 0;
548+
549+ for (i = len; i >= 0 ; i -= PRAM_PAGESIZE) {
550+ adf7242_write_reg(lp, REG_PRAMPG, page);
551+
552+ xfer_buf.len = i >= PRAM_PAGESIZE ? PRAM_PAGESIZE : i,
553+ xfer_buf.tx_buf = &data[page * PRAM_PAGESIZE],
554+
555+ spi_message_init(&msg);
556+ spi_message_add_tail(&xfer_head, &msg);
557+ spi_message_add_tail(&xfer_buf, &msg);
558+
559+ mutex_lock(&lp->bmux);
560+ status = spi_sync(lp->spi, &msg);
561+ mutex_unlock(&lp->bmux);
562+ page++;
563+ }
564+
565+ return status;
566+}
567+
568+static int adf7242_ed(struct ieee802154_dev *dev, u8 *level)
569+{
570+ struct adf7242_local *lp = dev->priv;
571+ int ret;
572+
573+ DBG(2, "%s :Enter\n", __func__);
574+#if 0
575+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
576+ adf7242_cmd(lp, CMD_RC_CCA);
577+ adf7242_wait_status(lp, RC_STATUS_PHY_RDY);
578+#else
579+ udelay(128);
580+#endif
581+ ret = adf7242_read_reg(lp, REG_RRB, level);
582+ adf7242_cmd(lp, CMD_RC_RX);
583+ DBG(2, "%s :Exit\n", __func__);
584+
585+ return ret;
586+}
587+
588+static int adf7242_start(struct ieee802154_dev *dev)
589+{
590+ struct adf7242_local *lp = dev->priv;
591+ int ret;
592+
593+ DBG(2, "%s :Enter\n", __func__);
594+ ret = adf7242_cmd(lp, CMD_RC_RX);
595+ DBG(2, "%s :Exit\n", __func__);
596+
597+ return ret;
598+}
599+
600+static void adf7242_stop(struct ieee802154_dev *dev)
601+{
602+ struct adf7242_local *lp = dev->priv;
603+
604+ DBG(2, "%s :Enter\n", __func__);
605+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
606+ DBG(2, "%s :Exit\n", __func__);
607+}
608+
609+static int adf7242_channel(struct ieee802154_dev *dev, int page, int channel)
610+{
611+ struct adf7242_local *lp = dev->priv;
612+ unsigned long freq;
613+
614+ DBG(2, "%s :Enter\n", __func__);
615+ DBG(1, "%s :Channel=%d\n", __func__, channel);
616+
617+ might_sleep();
618+
619+ BUG_ON(page != 0);
620+ BUG_ON(channel < 11);
621+ BUG_ON(channel > 26);
622+
623+ freq = (2405 + 5 * (channel - 11)) * 100;
624+
625+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
626+
627+ adf7242_write_reg(lp, REG_CH_FREQ0, freq);
628+ adf7242_write_reg(lp, REG_CH_FREQ1, freq >> 8);
629+ adf7242_write_reg(lp, REG_CH_FREQ2, freq >> 16);
630+
631+ adf7242_cmd(lp, CMD_RC_RX);
632+
633+ dev->phy->current_channel = channel;
634+ DBG(2, "%s :Exit\n", __func__);
635+
636+ return 0;
637+}
638+
639+static int adf7242_set_hw_addr_filt(struct ieee802154_dev *dev,
640+ struct ieee802154_hw_addr_filt *filt,
641+ unsigned long changed)
642+{
643+ struct adf7242_local *lp = dev->priv;
644+ u8 reg;
645+
646+ DBG(2, "%s :Enter\n", __func__);
647+ DBG(1, "%s :Changed=0x%lX\n", __func__, changed);
648+
649+ might_sleep();
650+
651+ if (changed & IEEE802515_IEEEADDR_CHANGED) {
652+ adf7242_write_reg(lp, REG_IEEE_ADDR_0, filt->ieee_addr[7]);
653+ adf7242_write_reg(lp, REG_IEEE_ADDR_1, filt->ieee_addr[6]);
654+ adf7242_write_reg(lp, REG_IEEE_ADDR_2, filt->ieee_addr[5]);
655+ adf7242_write_reg(lp, REG_IEEE_ADDR_3, filt->ieee_addr[4]);
656+ adf7242_write_reg(lp, REG_IEEE_ADDR_4, filt->ieee_addr[3]);
657+ adf7242_write_reg(lp, REG_IEEE_ADDR_5, filt->ieee_addr[2]);
658+ adf7242_write_reg(lp, REG_IEEE_ADDR_6, filt->ieee_addr[1]);
659+ adf7242_write_reg(lp, REG_IEEE_ADDR_7, filt->ieee_addr[0]);
660+ }
661+
662+ if (changed & IEEE802515_SADDR_CHANGED) {
663+ adf7242_write_reg(lp, REG_SHORT_ADDR_0, filt->short_addr);
664+ adf7242_write_reg(lp, REG_SHORT_ADDR_1, filt->short_addr >> 8);
665+ }
666+
667+ if (changed & IEEE802515_PANID_CHANGED) {
668+ adf7242_write_reg(lp, REG_PAN_ID0, filt->pan_id);
669+ adf7242_write_reg(lp, REG_PAN_ID1, filt->pan_id >> 8);
670+ }
671+
672+ if (changed & IEEE802515_PANC_CHANGED) {
673+ adf7242_read_reg(lp, REG_AUTO_CFG, &reg);
674+ if (filt->pan_coord)
675+ reg |= IS_PANCOORD;
676+ else
677+ reg &= ~IS_PANCOORD;
678+ adf7242_write_reg(lp, REG_AUTO_CFG, reg);
679+ }
680+
681+ DBG(2, "%s :Exit\n", __func__);
682+ return 0;
683+}
684+
685+static int adf7242_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
686+{
687+ struct adf7242_local *lp = dev->priv;
688+ int ret;
689+ unsigned long flags;
690+
691+ DBG(2, "%s :Enter\n", __func__);
692+
693+ spin_lock_irqsave(&lp->lock, flags);
694+ BUG_ON(lp->is_tx);
695+ lp->is_tx = 1;
696+ spin_unlock_irqrestore(&lp->lock, flags);
697+
698+ ret = adf7242_write_fbuf(lp, skb->data, skb->len);
699+ if (ret)
700+ goto err_rx;
701+
702+ if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA) {
703+ ret = adf7242_cmd(lp, CMD_RC_PHY_RDY);
704+ ret |= adf7242_cmd(lp, CMD_RC_CSMACA);
705+ } else {
706+ ret = adf7242_cmd(lp, CMD_RC_TX);
707+ }
708+
709+ if (ret)
710+ goto err_rx;
711+
712+ ret = wait_for_completion_interruptible(&lp->tx_complete);
713+
714+ if (ret < 0)
715+ goto err_rx;
716+
717+ DBG(2, "%s :Exit\n", __func__);
718+ return ret;
719+
720+err_rx:
721+ spin_lock_irqsave(&lp->lock, flags);
722+ lp->is_tx = 0;
723+ spin_unlock_irqrestore(&lp->lock, flags);
724+ return ret;
725+}
726+
727+static int adf7242_rx(struct adf7242_local *lp)
728+{
729+ u8 len = 128;
730+ u8 lqi = 0;
731+ int ret;
732+ struct sk_buff *skb;
733+
734+ DBG(2, "%s :Enter\n", __func__);
735+
736+ skb = alloc_skb(len, GFP_KERNEL);
737+ if (!skb)
738+ return -ENOMEM;
739+
740+ ret = adf7242_read_fbuf(lp, skb_put(skb, len), &len, &lqi);
741+
742+ adf7242_cmd(lp, CMD_RC_RX);
743+
744+ skb_trim(skb, len - 2); /* We do not put RSSI/LQI or CRC into the frame */
745+
746+ if (len < 2) {
747+ kfree_skb(skb);
748+ return -EINVAL;
749+ }
750+
751+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
752+
753+ DBG(1, "%s: %d %d %x\n", __func__, ret, len, lqi);
754+ DBG(2, "%s :Exit\n", __func__);
755+
756+ return 0;
757+}
758+
759+static struct ieee802154_ops adf7242_ops = {
760+ .owner = THIS_MODULE,
761+ .xmit = adf7242_xmit,
762+ .ed = adf7242_ed,
763+ .set_channel = adf7242_channel,
764+ .set_hw_addr_filt = adf7242_set_hw_addr_filt,
765+ .start = adf7242_start,
766+ .stop = adf7242_stop,
767+};
768+
769+static void adf7242_irqwork(struct work_struct *work)
770+{
771+ struct adf7242_local *lp =
772+ container_of(work, struct adf7242_local, irqwork);
773+ u8 irq1, auto_stat = 0, stat = 0;
774+ int ret;
775+ unsigned long flags;
776+
777+ DBG(2, "%s :Enter\n", __func__);
778+
779+ ret = adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
780+
781+ DBG(1, "%s IRQ1 = %X:\n%s%s%s%s%s%s%s%s\n", __func__, irq1,
782+ irq1 & IRQ_CCA_COMPLETE ? "IRQ_CCA_COMPLETE\n" : "",
783+ irq1 & IRQ_SFD_RX ? "IRQ_SFD_RX\n" : "",
784+ irq1 & IRQ_SFD_TX ? "IRQ_SFD_TX\n" : "",
785+ irq1 & IRQ_RX_PKT_RCVD ? "IRQ_RX_PKT_RCVD\n" : "",
786+ irq1 & IRQ_TX_PKT_SENT ? "IRQ_TX_PKT_SENT\n" : "",
787+ irq1 & IRQ_CSMA_CA ? "IRQ_CSMA_CA\n" : "",
788+ irq1 & IRQ_FRAME_VALID ? "IRQ_FRAME_VALID\n" : "",
789+ irq1 & IRQ_ADDRESS_VALID ? "IRQ_ADDRESS_VALID\n" : "");
790+
791+ adf7242_status(lp, &stat);
792+
793+ DBG(1, "%s STATUS = %X:\n%s\n%s%s%s%s%s\n", __func__, stat,
794+ stat & STAT_RC_READY ? "RC_READY" : "RC_BUSY",
795+ (stat & 0xf) == RC_STATUS_IDLE ? "RC_STATUS_IDLE" : "",
796+ (stat & 0xf) == RC_STATUS_MEAS ? "RC_STATUS_MEAS" : "",
797+ (stat & 0xf) == RC_STATUS_PHY_RDY ? "RC_STATUS_PHY_RDY" : "",
798+ (stat & 0xf) == RC_STATUS_RX ? "RC_STATUS_RX" : "",
799+ (stat & 0xf) == RC_STATUS_TX ? "RC_STATUS_TX" : "");
800+
801+ adf7242_write_reg(lp, REG_IRQ1_SRC1, irq1);
802+
803+ if (irq1 & IRQ_RX_PKT_RCVD) {
804+
805+ /* Wait until ACK is processed */
806+ if ((lp->mode & ADF_IEEE802154_HW_AACK) &&
807+ ((stat & RC_STATUS_MASK) != RC_STATUS_PHY_RDY))
808+ adf7242_wait_status(lp, RC_STATUS_PHY_RDY);
809+
810+ adf7242_rx(lp);
811+ }
812+
813+ if (irq1 & lp->tx_irq) {
814+
815+ if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA) {
816+ adf7242_read_reg(lp, REG_AUTO_STATUS, &auto_stat);
817+ auto_stat &= AUTO_STATUS_MASK;
818+
819+ DBG(1, "%s AUTO_STATUS = %X:\n%s%s%s%s\n",
820+ __func__, auto_stat,
821+ auto_stat == SUCCESS ? "SUCCESS" : "",
822+ auto_stat == SUCCESS_DATPEND ? "SUCCESS_DATPEND" : "",
823+ auto_stat == FAILURE_CSMACA ? "FAILURE_CSMACA" : "",
824+ auto_stat == FAILURE_NOACK ? "FAILURE_NOACK" : "");
825+
826+ /* save CSMA-CA completion status */
827+ lp->tx_stat = auto_stat;
828+ }
829+ spin_lock_irqsave(&lp->lock, flags);
830+ if (lp->is_tx) {
831+ lp->is_tx = 0;
832+ complete(&lp->tx_complete);
833+ }
834+ spin_unlock_irqrestore(&lp->lock, flags);
835+
836+ /* in case we just received a frame we are already in PHY_RX */
837+
838+ if (!(irq1 & IRQ_RX_PKT_RCVD))
839+ adf7242_cmd(lp, CMD_RC_RX);
840+ }
841+
842+ spin_lock_irqsave(&lp->lock, flags);
843+ if (lp->irq_disabled) {
844+ lp->irq_disabled = 0;
845+ enable_irq(lp->spi->irq);
846+ }
847+ spin_unlock_irqrestore(&lp->lock, flags);
848+
849+ DBG(2, "%s :Exit\n", __func__);
850+}
851+
852+static irqreturn_t adf7242_isr(int irq, void *data)
853+{
854+ struct adf7242_local *lp = data;
855+
856+ DBG(2, "%s :Enter\n", __func__);
857+
858+ spin_lock(&lp->lock);
859+ if (!lp->irq_disabled) {
860+ disable_irq_nosync(irq);
861+ lp->irq_disabled = 1;
862+ }
863+ spin_unlock(&lp->lock);
864+
865+ schedule_work(&lp->irqwork);
866+
867+ DBG(2, "%s :Exit\n", __func__);
868+
869+ return IRQ_HANDLED;
870+}
871+
872+
873+static int adf7242_hw_init(struct adf7242_local *lp)
874+{
875+ int ret;
876+ const struct firmware *fw;
877+
878+ DBG(2, "%s :Enter\n", __func__);
879+
880+ adf7242_cmd(lp, CMD_RC_IDLE);
881+
882+ if (lp->mode) {
883+ /* get ADF7242 addon firmware
884+ * build this driver as module
885+ * and place under /lib/firmware/adf7242_firmware.bin
886+ */
887+ ret = request_firmware(&fw, FIRMWARE, &lp->spi->dev);
888+ if (ret) {
889+ dev_err(&lp->spi->dev,
890+ "request_firmware() failed with %i\n", ret);
891+ return ret;
892+ }
893+
894+ adf7242_upload_firmware(lp, (u8 *) fw->data, fw->size);
895+ release_firmware(fw);
896+
897+ adf7242_write_reg(lp, REG_FFILT_CFG,
898+ ACCEPT_BEACON_FRAMES |
899+ ACCEPT_DATA_FRAMES |
900+ ACCEPT_ACK_FRAMES |
901+ ACCEPT_MACCMD_FRAMES |
902+ (lp->mode & ADF_IEEE802154_PROMISCUOUS_MODE ?
903+ ACCEPT_ALL_ADDRESS : 0) |
904+ ACCEPT_RESERVED_FRAMES);
905+
906+ adf7242_write_reg(lp, REG_AUTO_TX1,
907+ MAX_FRAME_RETRIES(lp->pdata->max_frame_retries) |
908+ MAX_CCA_RETRIES(lp->pdata->max_cca_retries));
909+
910+ adf7242_write_reg(lp, REG_AUTO_TX2,
911+ CSMA_MAX_BE(lp->pdata->max_csma_be) |
912+ CSMA_MIN_BE(lp->pdata->min_csma_be));
913+
914+ adf7242_write_reg(lp, REG_AUTO_CFG,
915+ (lp->mode & ADF_IEEE802154_HW_AACK ?
916+ RX_AUTO_ACK_EN : 0));
917+ }
918+
919+ adf7242_write_reg(lp, REG_PKT_CFG, lp->mode ? ADDON_EN : 0);
920+
921+ adf7242_write_reg(lp, REG_EXTPA_MSC, 0xF1);
922+ adf7242_write_reg(lp, REG_RXFE_CFG, 0x1D);
923+ adf7242_write_reg(lp, REG_IRQ1_EN0, 0);
924+
925+ adf7242_write_reg(lp, REG_IRQ1_EN1, IRQ_RX_PKT_RCVD | lp->tx_irq);
926+
927+ adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
928+ adf7242_write_reg(lp, REG_IRQ1_SRC0, 0xFF);
929+
930+ adf7242_cmd(lp, CMD_RC_PHY_RDY);
931+
932+ DBG(2, "%s :Exit\n", __func__);
933+
934+ return 0;
935+}
936+
937+static int adf7242_suspend(struct spi_device *spi, pm_message_t message)
938+{
939+ return 0;
940+}
941+
942+static int adf7242_resume(struct spi_device *spi)
943+{
944+ return 0;
945+}
946+
947+static ssize_t adf7242_show(struct device *dev,
948+ struct device_attribute *devattr,
949+ char *buf)
950+{
951+ struct adf7242_local *lp = dev_get_drvdata(dev);
952+ u8 stat;
953+
954+ adf7242_status(lp, &stat);
955+
956+ return sprintf(buf, "STATUS = %X:\n%s\n%s%s%s%s%s\n", stat,
957+ stat & STAT_RC_READY ? "RC_READY" : "RC_BUSY",
958+ (stat & 0xf) == RC_STATUS_IDLE ? "RC_STATUS_IDLE" : "",
959+ (stat & 0xf) == RC_STATUS_MEAS ? "RC_STATUS_MEAS" : "",
960+ (stat & 0xf) == RC_STATUS_PHY_RDY ? "RC_STATUS_PHY_RDY" : "",
961+ (stat & 0xf) == RC_STATUS_RX ? "RC_STATUS_RX" : "",
962+ (stat & 0xf) == RC_STATUS_TX ? "RC_STATUS_TX" : "");
963+
964+}
965+static DEVICE_ATTR(status, 0664, adf7242_show, NULL);
966+
967+static struct attribute *adf7242_attributes[] = {
968+ &dev_attr_status.attr,
969+ NULL
970+};
971+
972+static const struct attribute_group adf7242_attr_group = {
973+ .attrs = adf7242_attributes,
974+};
975+
976+static int __devinit adf7242_probe(struct spi_device *spi)
977+{
978+ struct adf7242_platform_data *pdata = spi->dev.platform_data;
979+ struct ieee802154_dev *dev;
980+ struct adf7242_local *lp;
981+ int ret;
982+
983+ if (!spi->irq) {
984+ dev_err(&spi->dev, "no IRQ specified\n");
985+ return -EINVAL;
986+ }
987+
988+ if (!pdata) {
989+ dev_err(&spi->dev, "no platform data?\n");
990+ return -ENODEV;
991+ }
992+
993+ dev = ieee802154_alloc_device(sizeof(*lp), &adf7242_ops);
994+ if (!dev)
995+ return -ENOMEM;
996+
997+ lp = dev->priv;
998+ lp->dev = dev;
999+ lp->spi = spi;
1000+ lp->pdata = pdata;
1001+ lp->mode = pdata->mode;
1002+
1003+ dev->priv = lp;
1004+ dev->parent = &spi->dev;
1005+ dev->extra_tx_headroom = 0;
1006+ /* We do support only 2.4 Ghz */
1007+
1008+ dev->phy->channels_supported[0] = 0x7FFF800;
1009+
1010+ if (!lp->mode) {
1011+ adf7242_ops.set_hw_addr_filt = NULL;
1012+ lp->tx_irq = IRQ_TX_PKT_SENT;
1013+ } else {
1014+ if ((lp->mode & ADF_IEEE802154_PROMISCUOUS_MODE) &&
1015+ (lp->mode & ADF_IEEE802154_HW_AACK))
1016+ lp->mode &= ~ADF_IEEE802154_HW_AACK;
1017+
1018+ if (lp->mode & ADF_IEEE802154_AUTO_CSMA_CA)
1019+ lp->tx_irq = IRQ_CSMA_CA;
1020+ else
1021+ lp->tx_irq = IRQ_TX_PKT_SENT;
1022+ }
1023+
1024+ dev->flags = IEEE802154_HW_OMIT_CKSUM |
1025+ (lp->mode & ADF_IEEE802154_HW_AACK ?
1026+ IEEE802154_HW_AACK : 0);
1027+
1028+ mutex_init(&lp->bmux);
1029+ INIT_WORK(&lp->irqwork, adf7242_irqwork);
1030+ spin_lock_init(&lp->lock);
1031+ init_completion(&lp->tx_complete);
1032+
1033+ spi_set_drvdata(spi, lp);
1034+
1035+ ret = adf7242_hw_init(lp);
1036+ if (ret)
1037+ goto err_hw_init;
1038+
1039+ ret = request_irq(spi->irq, adf7242_isr, IRQF_TRIGGER_HIGH,
1040+ dev_name(&spi->dev), lp);
1041+ if (ret)
1042+ goto err_hw_init;
1043+
1044+ ret = ieee802154_register_device(lp->dev);
1045+ if (ret)
1046+ goto err_irq;
1047+
1048+ dev_set_drvdata(&spi->dev, lp);
1049+
1050+ ret = sysfs_create_group(&spi->dev.kobj, &adf7242_attr_group);
1051+ if (ret)
1052+ goto out;
1053+
1054+ dev_info(&spi->dev, "mac802154 IRQ-%d registered\n", spi->irq);
1055+
1056+ return ret;
1057+
1058+out:
1059+ ieee802154_unregister_device(lp->dev);
1060+err_irq:
1061+ free_irq(spi->irq, lp);
1062+ flush_work(&lp->irqwork);
1063+err_hw_init:
1064+ spi_set_drvdata(spi, NULL);
1065+ mutex_destroy(&lp->bmux);
1066+ ieee802154_free_device(lp->dev);
1067+ return ret;
1068+}
1069+
1070+static int __devexit adf7242_remove(struct spi_device *spi)
1071+{
1072+ struct adf7242_local *lp = spi_get_drvdata(spi);
1073+
1074+ ieee802154_unregister_device(lp->dev);
1075+ free_irq(spi->irq, lp);
1076+ flush_work(&lp->irqwork);
1077+ spi_set_drvdata(spi, NULL);
1078+ mutex_destroy(&lp->bmux);
1079+ ieee802154_free_device(lp->dev);
1080+
1081+ return 0;
1082+}
1083+
1084+static struct spi_driver adf7242_driver = {
1085+ .driver = {
1086+ .name = "adf7242",
1087+ .owner = THIS_MODULE,
1088+ },
1089+ .probe = adf7242_probe,
1090+ .remove = __devexit_p(adf7242_remove),
1091+ .suspend = adf7242_suspend,
1092+ .resume = adf7242_resume,
1093+};
1094+
1095+static int __init adf7242_init(void)
1096+{
1097+ return spi_register_driver(&adf7242_driver);
1098+}
1099+module_init(adf7242_init);
1100+
1101+static void __exit adf7242_exit(void)
1102+{
1103+ spi_unregister_driver(&adf7242_driver);
1104+}
1105+module_exit(adf7242_exit);
1106+
1107+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
1108+MODULE_DESCRIPTION("ADF7242 Transceiver Driver");
1109+MODULE_LICENSE("GPL");
1110diff --git a/drivers/ieee802154/at86rf230.c b/drivers/ieee802154/at86rf230.c
1111new file mode 100644
1112index 0000000..8da82cf
1113--- /dev/null
1114@@ -0,0 +1,872 @@
1115+/*
1116+ * AT86RF230/RF231 driver
1117+ *
1118+ * Copyright (C) 2009 Siemens AG
1119+ *
1120+ * This program is free software; you can redistribute it and/or modify
1121+ * it under the terms of the GNU General Public License version 2
1122+ * as published by the Free Software Foundation.
1123+ *
1124+ * This program is distributed in the hope that it will be useful,
1125+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1126+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1127+ * GNU General Public License for more details.
1128+ *
1129+ * You should have received a copy of the GNU General Public License along
1130+ * with this program; if not, write to the Free Software Foundation, Inc.,
1131+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1132+ *
1133+ * Written by:
1134+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
1135+ */
1136+#include <linux/kernel.h>
1137+#include <linux/module.h>
1138+#include <linux/interrupt.h>
1139+#include <linux/gpio.h>
1140+#include <linux/delay.h>
1141+#include <linux/mutex.h>
1142+#include <linux/workqueue.h>
1143+#include <linux/spi/spi.h>
1144+#include <linux/spi/at86rf230.h>
1145+
1146+#ifdef CONFIG_OF
1147+#include <linux/of.h>
1148+#include <linux/of_gpio.h>
1149+#endif
1150+
1151+#include <net/mac802154.h>
1152+#include <net/wpan-phy.h>
1153+
1154+#include "at86rf230.h"
1155+
1156+
1157+struct at86rf230_local {
1158+ struct spi_device *spi;
1159+ int rstn, slp_tr, dig2;
1160+ void (*reset)(void *reset_data);
1161+ void *reset_data;
1162+
1163+ u8 part;
1164+ u8 vers;
1165+
1166+ u8 buf[2];
1167+ struct mutex bmux;
1168+
1169+ struct work_struct irqwork;
1170+ struct completion tx_complete;
1171+
1172+ struct ieee802154_dev *dev;
1173+
1174+ volatile unsigned is_tx:1;
1175+};
1176+
1177+
1178+static int
1179+__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
1180+{
1181+ u8 *buf = lp->buf;
1182+ int status;
1183+ struct spi_message msg;
1184+ struct spi_transfer xfer = {
1185+ .len = 2,
1186+ .tx_buf = buf,
1187+ };
1188+
1189+ buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
1190+ buf[1] = data;
1191+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1192+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1193+ spi_message_init(&msg);
1194+ spi_message_add_tail(&xfer, &msg);
1195+
1196+ status = spi_sync(lp->spi, &msg);
1197+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1198+ if (msg.status)
1199+ status = msg.status;
1200+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1201+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1202+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1203+
1204+ return status;
1205+}
1206+
1207+static int
1208+__at86rf230_read_subreg(struct at86rf230_local *lp,
1209+ u8 addr, u8 mask, int shift, u8 *data)
1210+{
1211+ u8 *buf = lp->buf;
1212+ int status;
1213+ struct spi_message msg;
1214+ struct spi_transfer xfer = {
1215+ .len = 2,
1216+ .tx_buf = buf,
1217+ .rx_buf = buf,
1218+ };
1219+
1220+ buf[0] = (addr & CMD_REG_MASK) | CMD_REG;
1221+ buf[1] = 0xff;
1222+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1223+ spi_message_init(&msg);
1224+ spi_message_add_tail(&xfer, &msg);
1225+
1226+ status = spi_sync(lp->spi, &msg);
1227+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1228+ if (msg.status)
1229+ status = msg.status;
1230+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1231+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1232+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1233+
1234+ if (status == 0)
1235+ *data = buf[1];
1236+
1237+ return status;
1238+}
1239+
1240+static int
1241+at86rf230_read_subreg(struct at86rf230_local *lp,
1242+ u8 addr, u8 mask, int shift, u8 *data)
1243+{
1244+ int status;
1245+
1246+ mutex_lock(&lp->bmux);
1247+ status = __at86rf230_read_subreg(lp, addr, mask, shift, data);
1248+ mutex_unlock(&lp->bmux);
1249+
1250+ return status;
1251+}
1252+
1253+static int
1254+at86rf230_write_subreg(struct at86rf230_local *lp,
1255+ u8 addr, u8 mask, int shift, u8 data)
1256+{
1257+ int status;
1258+ u8 val;
1259+
1260+ mutex_lock(&lp->bmux);
1261+ status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val);
1262+ if (status)
1263+ goto out;
1264+
1265+ val &= ~mask;
1266+ val |= (data << shift) & mask;
1267+
1268+ status = __at86rf230_write(lp, addr, val);
1269+out:
1270+ mutex_unlock(&lp->bmux);
1271+
1272+ return status;
1273+}
1274+
1275+static int
1276+at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len)
1277+{
1278+ u8 *buf = lp->buf;
1279+ int status;
1280+ struct spi_message msg;
1281+ struct spi_transfer xfer_head = {
1282+ .len = 2,
1283+ .tx_buf = buf,
1284+
1285+ };
1286+ struct spi_transfer xfer_buf = {
1287+ .len = len,
1288+ .tx_buf = data,
1289+ };
1290+
1291+ mutex_lock(&lp->bmux);
1292+ buf[0] = CMD_WRITE | CMD_FB;
1293+ buf[1] = len + 2; /* 2 bytes for CRC that isn't written */
1294+
1295+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1296+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1297+
1298+ spi_message_init(&msg);
1299+ spi_message_add_tail(&xfer_head, &msg);
1300+ spi_message_add_tail(&xfer_buf, &msg);
1301+
1302+ status = spi_sync(lp->spi, &msg);
1303+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1304+ if (msg.status)
1305+ status = msg.status;
1306+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1307+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1308+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1309+
1310+ mutex_unlock(&lp->bmux);
1311+ return status;
1312+}
1313+
1314+static int
1315+at86rf230_read_fbuf(struct at86rf230_local *lp, u8 *data, u8 *len, u8 *lqi)
1316+{
1317+ u8 *buf = lp->buf;
1318+ int status;
1319+ struct spi_message msg;
1320+ struct spi_transfer xfer_head = {
1321+ .len = 2,
1322+ .tx_buf = buf,
1323+ .rx_buf = buf,
1324+ };
1325+ struct spi_transfer xfer_head1 = {
1326+ .len = 2,
1327+ .tx_buf = buf,
1328+ .rx_buf = buf,
1329+ };
1330+ struct spi_transfer xfer_buf = {
1331+ .len = 0,
1332+ .rx_buf = data,
1333+ };
1334+
1335+ mutex_lock(&lp->bmux);
1336+
1337+ buf[0] = CMD_FB;
1338+ buf[1] = 0x00;
1339+
1340+ spi_message_init(&msg);
1341+ spi_message_add_tail(&xfer_head, &msg);
1342+
1343+ status = spi_sync(lp->spi, &msg);
1344+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1345+
1346+ if (buf[1] & 0x80) {
1347+ dev_err(&lp->spi->dev, "invalid PHR 0x%02x\n", buf[1]);
1348+ status = -EIO;
1349+ goto fail;
1350+ }
1351+ if (buf[1] >= *len) {
1352+ dev_err(&lp->spi->dev, "PHR 0x%02x >= buffer %d bytes\n",
1353+ buf[1], *len);
1354+ status = -EMSGSIZE;
1355+ goto fail;
1356+ }
1357+ xfer_buf.len = *(buf + 1) + 1;
1358+ *len = buf[1];
1359+
1360+ buf[0] = CMD_FB;
1361+ buf[1] = 0x00;
1362+
1363+ spi_message_init(&msg);
1364+ spi_message_add_tail(&xfer_head1, &msg);
1365+ spi_message_add_tail(&xfer_buf, &msg);
1366+
1367+ status = spi_sync(lp->spi, &msg);
1368+
1369+ if (msg.status)
1370+ status = msg.status;
1371+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
1372+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
1373+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
1374+
1375+ if (!status) {
1376+ if (lqi && *len > lp->buf[1])
1377+ *lqi = data[lp->buf[1]];
1378+ }
1379+
1380+fail:
1381+ mutex_unlock(&lp->bmux);
1382+
1383+ return status;
1384+}
1385+
1386+static int
1387+at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
1388+{
1389+ pr_debug("%s\n", __func__);
1390+ might_sleep();
1391+ BUG_ON(!level);
1392+ *level = 0xbe;
1393+ return 0;
1394+}
1395+
1396+static int
1397+at86rf230_state(struct ieee802154_dev *dev, int state)
1398+{
1399+ struct at86rf230_local *lp = dev->priv;
1400+ int rc;
1401+ u8 val;
1402+ u8 desired_status;
1403+
1404+ pr_debug("%s %d\n", __func__/*, priv->cur_state*/, state);
1405+ might_sleep();
1406+
1407+ if (state == STATE_FORCE_TX_ON)
1408+ desired_status = STATE_TX_ON;
1409+ else if (state == STATE_FORCE_TRX_OFF)
1410+ desired_status = STATE_TRX_OFF;
1411+ else
1412+ desired_status = state;
1413+
1414+ do {
1415+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
1416+ if (rc)
1417+ goto err;
1418+ pr_debug("%s val1 = %x\n", __func__, val);
1419+ } while (val == STATE_TRANSITION_IN_PROGRESS);
1420+
1421+ if (val == desired_status)
1422+ return 0;
1423+
1424+ /* state is equal to phy states */
1425+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, state);
1426+ if (rc)
1427+ goto err;
1428+
1429+ do {
1430+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
1431+ if (rc)
1432+ goto err;
1433+ pr_debug("%s val2 = %x\n", __func__, val);
1434+ } while (val == STATE_TRANSITION_IN_PROGRESS);
1435+
1436+
1437+ if (val == desired_status)
1438+ return 0;
1439+ if (state == STATE_RX_ON && val == STATE_BUSY_RX)
1440+ return 0;
1441+
1442+ pr_err("%s unexpected state change: %d, asked for %d\n", __func__,
1443+ val, state);
1444+ return -EBUSY;
1445+
1446+err:
1447+ pr_err("%s error: %d\n", __func__, rc);
1448+ return rc;
1449+}
1450+
1451+static int
1452+at86rf230_start(struct ieee802154_dev *dev)
1453+{
1454+ struct at86rf230_local *lp = dev->priv;
1455+ u8 rc;
1456+
1457+ rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
1458+ if (rc)
1459+ return rc;
1460+ return at86rf230_state(dev, STATE_RX_ON);
1461+}
1462+
1463+static void
1464+at86rf230_stop(struct ieee802154_dev *dev)
1465+{
1466+ at86rf230_state(dev, STATE_FORCE_TRX_OFF);
1467+}
1468+
1469+static int
1470+at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
1471+{
1472+ struct at86rf230_local *lp = dev->priv;
1473+ int rc;
1474+
1475+ pr_debug("%s %d\n", __func__, channel);
1476+ might_sleep();
1477+
1478+ BUG_ON(page != 0);
1479+ BUG_ON(channel < 11);
1480+ BUG_ON(channel > 26);
1481+
1482+ rc = at86rf230_write_subreg(lp, SR_CHANNEL, channel);
1483+ msleep(1); /* Wait for PLL */
1484+ dev->phy->current_channel = channel;
1485+
1486+ return 0;
1487+}
1488+
1489+/* FIXME:
1490+ * This function currently is a mess. It uses flush_work to guard
1491+ * against concurrent irqwork, etc. One has to use mutexes intead. */
1492+static int
1493+at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
1494+{
1495+ struct at86rf230_local *lp = dev->priv;
1496+ int rc;
1497+
1498+ pr_debug("%s\n", __func__);
1499+
1500+ might_sleep();
1501+
1502+ BUG_ON(lp->is_tx);
1503+ INIT_COMPLETION(lp->tx_complete);
1504+
1505+ rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
1506+ if (rc)
1507+ goto err;
1508+
1509+ synchronize_irq(lp->spi->irq);
1510+ flush_work(&lp->irqwork);
1511+
1512+ lp->is_tx = 1;
1513+
1514+ rc = at86rf230_write_fbuf(lp, skb->data, skb->len);
1515+ if (rc)
1516+ goto err_rx;
1517+
1518+ if (gpio_is_valid(lp->slp_tr)) {
1519+ gpio_set_value(lp->slp_tr, 1);
1520+ udelay(80); /* > 62.5 */
1521+ gpio_set_value(lp->slp_tr, 0);
1522+ } else {
1523+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
1524+ if (rc)
1525+ goto err_rx;
1526+ }
1527+
1528+ /* FIXME: the logic is really strange here. Datasheet doesn't
1529+ * provide us enough info about behaviour in such cases.
1530+ * Basically either we were interrupted here, or we have lost
1531+ * the interrupt. Most probably this should be changed to
1532+ * wait_for_completion_timeout() and handle it's results
1533+ */
1534+ rc = wait_for_completion_interruptible(&lp->tx_complete);
1535+ if (rc < 0)
1536+ goto err_state;
1537+
1538+ lp->is_tx = 0;
1539+
1540+ rc = at86rf230_start(dev);
1541+ return rc;
1542+
1543+err_state:
1544+ /* try to recover from possibly problematic state */
1545+ at86rf230_state(dev, STATE_FORCE_TX_ON);
1546+ synchronize_irq(lp->spi->irq);
1547+ flush_work(&lp->irqwork);
1548+ lp->is_tx = 0;
1549+err_rx:
1550+ at86rf230_start(dev);
1551+err:
1552+ if (rc)
1553+ pr_err("%s error: %d\n", __func__, rc);
1554+
1555+ return rc;
1556+}
1557+
1558+static int at86rf230_rx(struct at86rf230_local *lp)
1559+{
1560+ u8 len = 128, lqi = 0;
1561+ int rc, rc2;
1562+ struct sk_buff *skb;
1563+
1564+ skb = alloc_skb(len, GFP_KERNEL);
1565+ if (!skb)
1566+ return -ENOMEM;
1567+
1568+ /* FIXME: process return status */
1569+ rc = at86rf230_write_subreg(lp, SR_RX_PDT_DIS, 1);
1570+ rc2 = at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi);
1571+ rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
1572+ rc = at86rf230_write_subreg(lp, SR_RX_PDT_DIS, 0);
1573+ if (rc2 < 0)
1574+ goto err_fbuf;
1575+
1576+ if (len < 2)
1577+ goto err;
1578+
1579+ skb_trim(skb, len-2); /* We do not put CRC into the frame */
1580+
1581+
1582+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
1583+
1584+ dev_dbg(&lp->spi->dev, "READ_FBUF: %d %d %x\n", rc, len, lqi);
1585+
1586+ return 0;
1587+err:
1588+ pr_debug("%s: received frame is too small\n", __func__);
1589+
1590+err_fbuf:
1591+ kfree_skb(skb);
1592+ return -EINVAL;
1593+}
1594+
1595+static struct ieee802154_ops at86rf230_ops = {
1596+ .owner = THIS_MODULE,
1597+ .xmit = at86rf230_xmit,
1598+ .ed = at86rf230_ed,
1599+ .set_channel = at86rf230_channel,
1600+ .start = at86rf230_start,
1601+ .stop = at86rf230_stop,
1602+};
1603+
1604+static void at86rf230_irqwork(struct work_struct *work)
1605+{
1606+ struct at86rf230_local *lp =
1607+ container_of(work, struct at86rf230_local, irqwork);
1608+ u8 status = 0, val;
1609+ int rc;
1610+
1611+ dev_dbg(&lp->spi->dev, "IRQ Worker\n");
1612+
1613+ do {
1614+ rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
1615+ status |= val;
1616+ dev_dbg(&lp->spi->dev, "IRQ Status: %02x\n", status);
1617+
1618+ status &= ~IRQ_PLL_LOCK; /* ignore */
1619+ status &= ~IRQ_RX_START; /* ignore */
1620+ status &= ~IRQ_AMI; /* ignore */
1621+ status &= ~IRQ_TRX_UR; /* FIXME: possibly handle ???*/
1622+
1623+ if (status & IRQ_TRX_END) {
1624+ status &= ~IRQ_TRX_END;
1625+ if (lp->is_tx)
1626+ complete(&lp->tx_complete);
1627+ else
1628+ at86rf230_rx(lp);
1629+ }
1630+
1631+ } while (status != 0);
1632+
1633+ enable_irq(lp->spi->irq);
1634+}
1635+
1636+static irqreturn_t at86rf230_isr(int irq, void *data)
1637+{
1638+ struct at86rf230_local *lp = data;
1639+
1640+ dev_dbg(&lp->spi->dev, "IRQ!\n");
1641+
1642+ disable_irq_nosync(irq);
1643+ schedule_work(&lp->irqwork);
1644+
1645+ return IRQ_HANDLED;
1646+}
1647+
1648+
1649+static int at86rf230_hw_init(struct at86rf230_local *lp)
1650+{
1651+ u8 status;
1652+ int rc;
1653+
1654+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
1655+ if (rc)
1656+ return rc;
1657+
1658+ dev_info(&lp->spi->dev, "Status: %02x\n", status);
1659+ if (status == STATE_P_ON) {
1660+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TRX_OFF);
1661+ if (rc)
1662+ return rc;
1663+ msleep(1);
1664+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
1665+ if (rc)
1666+ return rc;
1667+ dev_info(&lp->spi->dev, "Status: %02x\n", status);
1668+ }
1669+
1670+ rc = at86rf230_write_subreg(lp, SR_IRQ_MASK,
1671+ /*IRQ_TRX_UR | IRQ_CCA_ED | IRQ_TRX_END | IRQ_PLL_UNL | IRQ_PLL_LOCK*/ 0xff);
1672+ if (rc)
1673+ return rc;
1674+
1675+ /* CLKM changes are applied immediately */
1676+ rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00);
1677+ if (rc)
1678+ return rc;
1679+
1680+ /* Turn CLKM Off */
1681+ rc = at86rf230_write_subreg(lp, SR_CLKM_CTRL, 0x00);
1682+ if (rc)
1683+ return rc;
1684+
1685+ msleep(100);
1686+
1687+ rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
1688+ if (rc)
1689+ return rc;
1690+ msleep(1);
1691+
1692+ rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
1693+ if (rc)
1694+ return rc;
1695+ dev_info(&lp->spi->dev, "Status: %02x\n", status);
1696+
1697+ rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
1698+ if (rc)
1699+ return rc;
1700+ if (!status) {
1701+ dev_err(&lp->spi->dev, "DVDD error\n");
1702+ return -EINVAL;
1703+ }
1704+
1705+ rc = at86rf230_read_subreg(lp, SR_AVDD_OK, &status);
1706+ if (rc)
1707+ return rc;
1708+ if (!status) {
1709+ dev_err(&lp->spi->dev, "AVDD error\n");
1710+ return -EINVAL;
1711+ }
1712+
1713+ return 0;
1714+}
1715+
1716+static int at86rf230_suspend(struct spi_device *spi, pm_message_t message)
1717+{
1718+ return 0;
1719+}
1720+
1721+static int at86rf230_resume(struct spi_device *spi)
1722+{
1723+ return 0;
1724+}
1725+
1726+#ifdef CONFIG_OF
1727+static int at86rf230_fill_data(struct spi_device *spi)
1728+{
1729+ struct device_node *np = spi->dev.of_node;
1730+ struct at86rf230_local *lp = spi_get_drvdata(spi);
1731+ struct at86rf230_platform_data *pdata = spi->dev.platform_data;
1732+ enum of_gpio_flags gpio_flags;
1733+
1734+ if (pdata) {
1735+ lp->rstn = pdata->rstn;
1736+ lp->slp_tr = pdata->slp_tr;
1737+ lp->dig2 = pdata->dig2;
1738+ lp->reset = pdata->reset;
1739+ lp->reset_data = pdata->reset_data;
1740+
1741+ return 0;
1742+ }
1743+
1744+ if (!np) {
1745+ dev_err(&spi->dev, "no platform_data and no node data\n");
1746+ return -EINVAL;
1747+ }
1748+
1749+ lp->rstn = of_get_gpio_flags(np, 0, &gpio_flags);
1750+ if (!gpio_is_valid(lp->rstn)) {
1751+ dev_err(&spi->dev, "no RSTN GPIO!\n");
1752+ return -EINVAL;
1753+ }
1754+
1755+ lp->slp_tr = of_get_gpio_flags(np, 1, &gpio_flags);
1756+ lp->dig2 = of_get_gpio_flags(np, 2, &gpio_flags);
1757+
1758+ lp->reset = NULL;
1759+
1760+ return 0;
1761+}
1762+#else
1763+static int at86rf230_fill_data(struct spi_device *spi)
1764+{
1765+ struct at86rf230_local *lp = spi_get_drvdata(spi);
1766+ struct at86rf230_platform_data *pdata = spi->dev.platform_data;
1767+
1768+ if (!pdata) {
1769+ dev_err(&spi->dev, "no platform_data\n");
1770+ return -EINVAL;
1771+ }
1772+
1773+ lp->rstn = pdata->rstn;
1774+ lp->slp_tr = pdata->slp_tr;
1775+ lp->dig2 = pdata->dig2;
1776+ lp->reset = pdata->reset;
1777+ lp->reset_data = pdata->reset_data;
1778+
1779+ return 0;
1780+}
1781+#endif
1782+
1783+static int __devinit at86rf230_probe(struct spi_device *spi)
1784+{
1785+ struct ieee802154_dev *dev;
1786+ struct at86rf230_local *lp;
1787+ u8 man_id_0, man_id_1;
1788+ int rc;
1789+ const char *chip;
1790+ int supported = 0;
1791+
1792+ if (spi->irq < 0) {
1793+ dev_err(&spi->dev, "no IRQ specified\n");
1794+ return -EINVAL;
1795+ }
1796+
1797+ dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
1798+ if (!dev)
1799+ return -ENOMEM;
1800+
1801+ lp = dev->priv;
1802+ lp->dev = dev;
1803+
1804+ lp->spi = spi;
1805+
1806+ dev->priv = lp;
1807+ dev->parent = &spi->dev;
1808+ dev->extra_tx_headroom = 0;
1809+ /* We do support only 2.4 Ghz */
1810+ dev->phy->channels_supported[0] = 0x7FFF800;
1811+ dev->flags = IEEE802154_HW_OMIT_CKSUM;
1812+
1813+ mutex_init(&lp->bmux);
1814+ INIT_WORK(&lp->irqwork, at86rf230_irqwork);
1815+ init_completion(&lp->tx_complete);
1816+
1817+ spi_set_drvdata(spi, lp);
1818+
1819+ rc = at86rf230_fill_data(spi);
1820+ if (rc)
1821+ goto err_fill;
1822+
1823+ if (gpio_is_valid(lp->rstn)) {
1824+ rc = gpio_request(lp->rstn, "rstn");
1825+ if (rc)
1826+ goto err_rstn;
1827+ }
1828+
1829+ if (gpio_is_valid(lp->slp_tr)) {
1830+ rc = gpio_request(lp->slp_tr, "slp_tr");
1831+ if (rc)
1832+ goto err_slp_tr;
1833+ }
1834+
1835+ if (gpio_is_valid(lp->rstn)) {
1836+ rc = gpio_direction_output(lp->rstn, 1);
1837+ if (rc)
1838+ goto err_gpio_dir;
1839+ }
1840+
1841+ if (gpio_is_valid(lp->slp_tr)) {
1842+ rc = gpio_direction_output(lp->slp_tr, 0);
1843+ if (rc)
1844+ goto err_gpio_dir;
1845+ }
1846+
1847+ /* Reset */
1848+ if (lp->reset)
1849+ lp->reset(lp->reset_data);
1850+ else {
1851+ msleep(1);
1852+ gpio_set_value(lp->rstn, 0);
1853+ msleep(1);
1854+ gpio_set_value(lp->rstn, 1);
1855+ msleep(1);
1856+ }
1857+
1858+ rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0);
1859+ if (rc)
1860+ goto err_gpio_dir;
1861+ rc = at86rf230_read_subreg(lp, SR_MAN_ID_1, &man_id_1);
1862+ if (rc)
1863+ goto err_gpio_dir;
1864+
1865+ if (man_id_1 != 0x00 || man_id_0 != 0x1f) {
1866+ dev_err(&spi->dev, "Non-Atmel device found (MAN_ID:"
1867+ "%02x %02x)\n", man_id_1, man_id_0);
1868+ rc = -EINVAL;
1869+ goto err_gpio_dir;
1870+ }
1871+
1872+ rc = at86rf230_read_subreg(lp, SR_PART_NUM, &lp->part);
1873+ if (rc)
1874+ goto err_gpio_dir;
1875+
1876+ rc = at86rf230_read_subreg(lp, SR_VERSION_NUM, &lp->vers);
1877+ if (rc)
1878+ goto err_gpio_dir;
1879+
1880+ switch (lp->part) {
1881+ case 2:
1882+ chip = "at86rf230";
1883+ /* supported = 1; FIXME: should be easy to support; */
1884+ break;
1885+ case 3:
1886+ chip = "at86rf231";
1887+ supported = 1;
1888+ break;
1889+ default:
1890+ chip = "UNKNOWN";
1891+ break;
1892+ }
1893+
1894+ dev_info(&spi->dev, "Detected %s chip version %d\n", chip, lp->vers);
1895+ if (!supported) {
1896+ rc = -ENOTSUPP;
1897+ goto err_gpio_dir;
1898+ }
1899+
1900+ rc = at86rf230_hw_init(lp);
1901+ if (rc)
1902+ goto err_gpio_dir;
1903+
1904+ rc = request_irq(spi->irq, at86rf230_isr, IRQF_SHARED,
1905+ dev_name(&spi->dev), lp);
1906+ if (rc)
1907+ goto err_gpio_dir;
1908+
1909+ dev_dbg(&spi->dev, "registered at86rf230\n");
1910+
1911+ rc = ieee802154_register_device(lp->dev);
1912+ if (rc)
1913+ goto err_irq;
1914+
1915+ return rc;
1916+
1917+err_irq:
1918+ disable_irq(spi->irq);
1919+ flush_work(&lp->irqwork);
1920+ free_irq(spi->irq, lp);
1921+err_gpio_dir:
1922+ if (gpio_is_valid(lp->slp_tr))
1923+ gpio_free(lp->slp_tr);
1924+err_slp_tr:
1925+ if (gpio_is_valid(lp->rstn))
1926+ gpio_free(lp->rstn);
1927+err_rstn:
1928+err_fill:
1929+ spi_set_drvdata(spi, NULL);
1930+ mutex_destroy(&lp->bmux);
1931+ ieee802154_free_device(lp->dev);
1932+ return rc;
1933+}
1934+
1935+static int __devexit at86rf230_remove(struct spi_device *spi)
1936+{
1937+ struct at86rf230_local *lp = spi_get_drvdata(spi);
1938+
1939+ /*
1940+ * @@@ this looks wrong - what if a frame arrives before
1941+ * disable_irq ? -- wa
1942+ */
1943+ ieee802154_unregister_device(lp->dev);
1944+
1945+ disable_irq(spi->irq);
1946+ flush_work(&lp->irqwork);
1947+ free_irq(spi->irq, lp);
1948+
1949+ if (gpio_is_valid(lp->slp_tr))
1950+ gpio_free(lp->slp_tr);
1951+ if (gpio_is_valid(lp->rstn))
1952+ gpio_free(lp->rstn);
1953+
1954+ spi_set_drvdata(spi, NULL);
1955+ mutex_destroy(&lp->bmux);
1956+ ieee802154_free_device(lp->dev);
1957+
1958+ dev_dbg(&spi->dev, "unregistered at86rf230\n");
1959+ return 0;
1960+}
1961+
1962+static struct spi_driver at86rf230_driver = {
1963+ .driver = {
1964+ .name = "at86rf230",
1965+ .owner = THIS_MODULE,
1966+ },
1967+ .probe = at86rf230_probe,
1968+ .remove = __devexit_p(at86rf230_remove),
1969+ .suspend = at86rf230_suspend,
1970+ .resume = at86rf230_resume,
1971+};
1972+
1973+static int __init at86rf230_init(void)
1974+{
1975+ return spi_register_driver(&at86rf230_driver);
1976+}
1977+module_init(at86rf230_init);
1978+
1979+static void __exit at86rf230_exit(void)
1980+{
1981+ spi_unregister_driver(&at86rf230_driver);
1982+}
1983+module_exit(at86rf230_exit);
1984+
1985+MODULE_DESCRIPTION("AT86RF230 Transceiver Driver");
1986+MODULE_LICENSE("GPL v2");
1987diff --git a/drivers/ieee802154/at86rf230.h b/drivers/ieee802154/at86rf230.h
1988new file mode 100644
1989index 0000000..fcb0e11
1990--- /dev/null
1991@@ -0,0 +1,211 @@
1992+/*
1993+ * AT86RF230/RF231 register and protocol definitions
1994+ *
1995+ * Copyright (C) 2009 Siemens AG
1996+ *
1997+ * This program is free software; you can redistribute it and/or modify
1998+ * it under the terms of the GNU General Public License version 2
1999+ * as published by the Free Software Foundation.
2000+ *
2001+ * This program is distributed in the hope that it will be useful,
2002+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2003+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2004+ * GNU General Public License for more details.
2005+ *
2006+ * You should have received a copy of the GNU General Public License along
2007+ * with this program; if not, write to the Free Software Foundation, Inc.,
2008+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2009+ *
2010+ * Written by:
2011+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
2012+ */
2013+
2014+#ifndef ATR86F230_H
2015+#define ATR86F230_H
2016+
2017+#define RG_TRX_STATUS (0x01)
2018+#define SR_TRX_STATUS 0x01, 0x1f, 0
2019+#define SR_RESERVED_01_3 0x01, 0x20, 5
2020+#define SR_CCA_STATUS 0x01, 0x40, 6
2021+#define SR_CCA_DONE 0x01, 0x80, 7
2022+#define RG_TRX_STATE (0x02)
2023+#define SR_TRX_CMD 0x02, 0x1f, 0
2024+#define SR_TRAC_STATUS 0x02, 0xe0, 5
2025+#define RG_TRX_CTRL_0 (0x03)
2026+#define SR_CLKM_CTRL 0x03, 0x07, 0
2027+#define SR_CLKM_SHA_SEL 0x03, 0x08, 3
2028+#define SR_PAD_IO_CLKM 0x03, 0x30, 4
2029+#define SR_PAD_IO 0x03, 0xc0, 6
2030+#define RG_TRX_CTRL_1 (0x04)
2031+#define SR_IRQ_POLARITY 0x04, 0x01, 0
2032+#define SR_IRQ_MASK_MODE 0x04, 0x02, 1
2033+#define SR_SPI_CMD_MODE 0x04, 0x0c, 2
2034+#define SR_RX_BL_CTRL 0x04, 0x10, 4
2035+#define SR_TX_AUTO_CRC_ON 0x04, 0x20, 5
2036+#define SR_IRQ_2_EXT_EN 0x04, 0x40, 6
2037+#define SR_PA_EXT_EN 0x04, 0x80, 7
2038+#define RG_PHY_TX_PWR (0x05)
2039+#define SR_TX_PWR 0x05, 0x0f, 0
2040+#define SR_PA_LT 0x05, 0x30, 4
2041+#define SR_PA_BUF_LT 0x05, 0xc0, 6
2042+#define RG_PHY_RSSI (0x06)
2043+#define SR_RSSI 0x06, 0x1f, 0
2044+#define SR_RND_VALUE 0x06, 0x60, 5
2045+#define SR_RX_CRC_VALID 0x06, 0x80, 7
2046+#define RG_PHY_ED_LEVEL (0x07)
2047+#define SR_ED_LEVEL 0x07, 0xff, 0
2048+#define RG_PHY_CC_CCA (0x08)
2049+#define SR_CHANNEL 0x08, 0x1f, 0
2050+#define SR_CCA_MODE 0x08, 0x60, 5
2051+#define SR_CCA_REQUEST 0x08, 0x80, 7
2052+#define RG_CCA_THRES (0x09)
2053+#define SR_CCA_ED_THRES 0x09, 0x0f, 0
2054+#define SR_RESERVED_09_1 0x09, 0xf0, 4
2055+#define RG_RX_CTRL (0x0a)
2056+#define SR_PDT_THRES 0x0a, 0x0f, 0
2057+#define SR_RESERVED_0a_1 0x0a, 0xf0, 4
2058+#define RG_SFD_VALUE (0x0b)
2059+#define SR_SFD_VALUE 0x0b, 0xff, 0
2060+#define RG_TRX_CTRL_2 (0x0c)
2061+#define SR_OQPSK_DATA_RATE 0x0c, 0x03, 0
2062+#define SR_RESERVED_0c_2 0x0c, 0x7c, 2
2063+#define SR_RX_SAFE_MODE 0x0c, 0x80, 7
2064+#define RG_ANT_DIV (0x0d)
2065+#define SR_ANT_CTRL 0x0d, 0x03, 0
2066+#define SR_ANT_EXT_SW_EN 0x0d, 0x04, 2
2067+#define SR_ANT_DIV_EN 0x0d, 0x08, 3
2068+#define SR_RESERVED_0d_2 0x0d, 0x70, 4
2069+#define SR_ANT_SEL 0x0d, 0x80, 7
2070+#define RG_IRQ_MASK (0x0e)
2071+#define SR_IRQ_MASK 0x0e, 0xff, 0
2072+#define RG_IRQ_STATUS (0x0f)
2073+#define SR_IRQ_0_PLL_LOCK 0x0f, 0x01, 0
2074+#define SR_IRQ_1_PLL_UNLOCK 0x0f, 0x02, 1
2075+#define SR_IRQ_2_RX_START 0x0f, 0x04, 2
2076+#define SR_IRQ_3_TRX_END 0x0f, 0x08, 3
2077+#define SR_IRQ_4_CCA_ED_DONE 0x0f, 0x10, 4
2078+#define SR_IRQ_5_AMI 0x0f, 0x20, 5
2079+#define SR_IRQ_6_TRX_UR 0x0f, 0x40, 6
2080+#define SR_IRQ_7_BAT_LOW 0x0f, 0x80, 7
2081+#define RG_VREG_CTRL (0x10)
2082+#define SR_RESERVED_10_6 0x10, 0x03, 0
2083+#define SR_DVDD_OK 0x10, 0x04, 2
2084+#define SR_DVREG_EXT 0x10, 0x08, 3
2085+#define SR_RESERVED_10_3 0x10, 0x30, 4
2086+#define SR_AVDD_OK 0x10, 0x40, 6
2087+#define SR_AVREG_EXT 0x10, 0x80, 7
2088+#define RG_BATMON (0x11)
2089+#define SR_BATMON_VTH 0x11, 0x0f, 0
2090+#define SR_BATMON_HR 0x11, 0x10, 4
2091+#define SR_BATMON_OK 0x11, 0x20, 5
2092+#define SR_RESERVED_11_1 0x11, 0xc0, 6
2093+#define RG_XOSC_CTRL (0x12)
2094+#define SR_XTAL_TRIM 0x12, 0x0f, 0
2095+#define SR_XTAL_MODE 0x12, 0xf0, 4
2096+#define RG_RX_SYN (0x15)
2097+#define SR_RX_PDT_LEVEL 0x15, 0x0f, 0
2098+#define SR_RESERVED_15_2 0x15, 0x70, 4
2099+#define SR_RX_PDT_DIS 0x15, 0x80, 7
2100+#define RG_XAH_CTRL_1 (0x17)
2101+#define SR_RESERVED_17_8 0x17, 0x01, 0
2102+#define SR_AACK_PROM_MODE 0x17, 0x02, 1
2103+#define SR_AACK_ACK_TIME 0x17, 0x04, 2
2104+#define SR_RESERVED_17_5 0x17, 0x08, 3
2105+#define SR_AACK_UPLD_RES_FT 0x17, 0x10, 4
2106+#define SR_AACK_FLTR_RES_FT 0x17, 0x20, 5
2107+#define SR_RESERVED_17_2 0x17, 0x40, 6
2108+#define SR_RESERVED_17_1 0x17, 0x80, 7
2109+#define RG_FTN_CTRL (0x18)
2110+#define SR_RESERVED_18_2 0x18, 0x7f, 0
2111+#define SR_FTN_START 0x18, 0x80, 7
2112+#define RG_PLL_CF (0x1a)
2113+#define SR_RESERVED_1a_2 0x1a, 0x7f, 0
2114+#define SR_PLL_CF_START 0x1a, 0x80, 7
2115+#define RG_PLL_DCU (0x1b)
2116+#define SR_RESERVED_1b_3 0x1b, 0x3f, 0
2117+#define SR_RESERVED_1b_2 0x1b, 0x40, 6
2118+#define SR_PLL_DCU_START 0x1b, 0x80, 7
2119+#define RG_PART_NUM (0x1c)
2120+#define SR_PART_NUM 0x1c, 0xff, 0
2121+#define RG_VERSION_NUM (0x1d)
2122+#define SR_VERSION_NUM 0x1d, 0xff, 0
2123+#define RG_MAN_ID_0 (0x1e)
2124+#define SR_MAN_ID_0 0x1e, 0xff, 0
2125+#define RG_MAN_ID_1 (0x1f)
2126+#define SR_MAN_ID_1 0x1f, 0xff, 0
2127+#define RG_SHORT_ADDR_0 (0x20)
2128+#define SR_SHORT_ADDR_0 0x20, 0xff, 0
2129+#define RG_SHORT_ADDR_1 (0x21)
2130+#define SR_SHORT_ADDR_1 0x21, 0xff, 0
2131+#define RG_PAN_ID_0 (0x22)
2132+#define SR_PAN_ID_0 0x22, 0xff, 0
2133+#define RG_PAN_ID_1 (0x23)
2134+#define SR_PAN_ID_1 0x23, 0xff, 0
2135+#define RG_IEEE_ADDR_0 (0x24)
2136+#define SR_IEEE_ADDR_0 0x24, 0xff, 0
2137+#define RG_IEEE_ADDR_1 (0x25)
2138+#define SR_IEEE_ADDR_1 0x25, 0xff, 0
2139+#define RG_IEEE_ADDR_2 (0x26)
2140+#define SR_IEEE_ADDR_2 0x26, 0xff, 0
2141+#define RG_IEEE_ADDR_3 (0x27)
2142+#define SR_IEEE_ADDR_3 0x27, 0xff, 0
2143+#define RG_IEEE_ADDR_4 (0x28)
2144+#define SR_IEEE_ADDR_4 0x28, 0xff, 0
2145+#define RG_IEEE_ADDR_5 (0x29)
2146+#define SR_IEEE_ADDR_5 0x29, 0xff, 0
2147+#define RG_IEEE_ADDR_6 (0x2a)
2148+#define SR_IEEE_ADDR_6 0x2a, 0xff, 0
2149+#define RG_IEEE_ADDR_7 (0x2b)
2150+#define SR_IEEE_ADDR_7 0x2b, 0xff, 0
2151+#define RG_XAH_CTRL_0 (0x2c)
2152+#define SR_SLOTTED_OPERATION 0x2c, 0x01, 0
2153+#define SR_MAX_CSMA_RETRIES 0x2c, 0x0e, 1
2154+#define SR_MAX_FRAME_RETRIES 0x2c, 0xf0, 4
2155+#define RG_CSMA_SEED_0 (0x2d)
2156+#define SR_CSMA_SEED_0 0x2d, 0xff, 0
2157+#define RG_CSMA_SEED_1 (0x2e)
2158+#define SR_CSMA_SEED_1 0x2e, 0x07, 0
2159+#define SR_AACK_I_AM_COORD 0x2e, 0x08, 3
2160+#define SR_AACK_DIS_ACK 0x2e, 0x10, 4
2161+#define SR_AACK_SET_PD 0x2e, 0x20, 5
2162+#define SR_AACK_FVN_MODE 0x2e, 0xc0, 6
2163+#define RG_CSMA_BE (0x2f)
2164+#define SR_MIN_BE 0x2f, 0x0f, 0
2165+#define SR_MAX_BE 0x2f, 0xf0, 4
2166+
2167+#define CMD_REG 0x80
2168+#define CMD_REG_MASK 0x3f
2169+#define CMD_WRITE 0x40
2170+#define CMD_FB 0x20
2171+
2172+#define IRQ_BAT_LOW (1 << 7)
2173+#define IRQ_TRX_UR (1 << 6)
2174+#define IRQ_AMI (1 << 5)
2175+#define IRQ_CCA_ED (1 << 4)
2176+#define IRQ_TRX_END (1 << 3)
2177+#define IRQ_RX_START (1 << 2)
2178+#define IRQ_PLL_UNL (1 << 1)
2179+#define IRQ_PLL_LOCK (1 << 0)
2180+
2181+#define STATE_P_ON 0x00 /* BUSY */
2182+#define STATE_BUSY_RX 0x01
2183+#define STATE_BUSY_TX 0x02
2184+#define STATE_FORCE_TRX_OFF 0x03
2185+#define STATE_FORCE_TX_ON 0x04 /* IDLE */
2186+/* 0x05 */ /* INVALID_PARAMETER */
2187+#define STATE_RX_ON 0x06
2188+/* 0x07 */ /* SUCCESS */
2189+#define STATE_TRX_OFF 0x08
2190+#define STATE_TX_ON 0x09
2191+/* 0x0a - 0x0e */ /* 0x0a - UNSUPPORTED_ATTRIBUTE */
2192+#define STATE_SLEEP 0x0F
2193+#define STATE_BUSY_RX_AACK 0x11
2194+#define STATE_BUSY_TX_ARET 0x12
2195+#define STATE_BUSY_RX_AACK_ON 0x16
2196+#define STATE_BUSY_TX_ARET_ON 0x19
2197+#define STATE_RX_ON_NOCLK 0x1C
2198+#define STATE_RX_AACK_ON_NOCLK 0x1D
2199+#define STATE_BUSY_RX_AACK_NOCLK 0x1E
2200+#define STATE_TRANSITION_IN_PROGRESS 0x1F
2201+
2202+#endif /* !ATR86F230_H */
2203diff --git a/drivers/ieee802154/cc2420.c b/drivers/ieee802154/cc2420.c
2204new file mode 100644
2205index 0000000..50761de
2206--- /dev/null
2207@@ -0,0 +1,859 @@
2208+/*
2209+ * This program is free software; you can redistribute it and/or modify
2210+ * it under the terms of the GNU General Public License version 2
2211+ * as published by the Free Software Foundation.
2212+ *
2213+ * This program is distributed in the hope that it will be useful,
2214+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2215+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2216+ * GNU General Public License for more details.
2217+ *
2218+ * You should have received a copy of the GNU General Public License along
2219+ * with this program; if not, write to the Free Software Foundation, Inc.,
2220+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2221+ *
2222+ * Author: Jonathan Cameron <jic23@cam.ac.uk>
2223+ *
2224+ * Modified 2010: xue liu <liuxuenetmail@gmail.com>
2225+ */
2226+
2227+#include <linux/kernel.h>
2228+#include <linux/module.h>
2229+#include <linux/mutex.h>
2230+#include <linux/spinlock.h>
2231+#include <linux/gpio.h>
2232+#include <linux/delay.h>
2233+#include <linux/interrupt.h>
2234+#include <linux/workqueue.h>
2235+#include <linux/spi/spi.h>
2236+#include <linux/spi/cc2420.h>
2237+#include <linux/skbuff.h>
2238+#include <linux/irq.h>
2239+#include <net/mac802154.h>
2240+#include <net/wpan-phy.h>
2241+
2242+#define CC2420_WRITEREG(x) (x)
2243+#define CC2420_READREG(x) (0x40 | x)
2244+#define CC2420_RAMADDR(x) ((x & 0x7F) | 0x80)
2245+#define CC2420_RAMBANK(x) ((x >> 1) & 0xc0)
2246+#define CC2420_WRITERAM(x) (x)
2247+#define CC2420_READRAM(x) (0x20 | x)
2248+
2249+#define CC2420_FREQ_MASK 0x3FF
2250+#define CC2420_ADR_DECODE_MASK 0x0B00
2251+#define CC2420_FIFOP_THR_MASK 0x003F
2252+#define CC2420_CRC_MASK 0x80
2253+#define CC2420_RSSI_MASK 0x7F
2254+#define CC2420_FSMSTATE_MASK 0x2F
2255+
2256+#define CC2420_MANFIDLOW 0x233D
2257+#define CC2420_MANFIDHIGH 0x3000 /* my chip appears to version 3 - broaden this with testing */
2258+
2259+#define RSSI_OFFSET 45
2260+
2261+#define STATE_PDOWN 0
2262+#define STATE_IDLE 1
2263+#define STATE_RX_CALIBRATE 2
2264+#define STATE_RX_CALIBRATE2 40
2265+
2266+#define STATE_RX_SFD_SEARCH_MIN 3
2267+#define STATE_RX_SFD_SEARCH_MAX 6
2268+#define STATE_RX_FRAME 16
2269+#define STATE_RX_FRAME2 40
2270+#define STATE_RX_WAIT 14
2271+#define STATE_RX_OVERFLOW 17
2272+#define STATE_TX_ACK_CALIBRATE 48
2273+#define STATE_TX_ACK_PREAMBLE_MIN 49
2274+#define STATE_TX_ACK_PREAMBLE_MAX 51
2275+#define STATE_TX_ACK_MIN 52
2276+#define STATE_TX_ACK_MAX 54
2277+#define STATE_TX_CALIBRATE 32
2278+#define STATE_TX_PREAMBLE_MIN 34
2279+#define STATE_TX_PREAMBLE_MAX 36
2280+#define STATE_TX_FRAME_MIN 37
2281+#define STATE_TX_FRAME_MAX 39
2282+#define STATE_TX_UNDERFLOW 56
2283+
2284+struct cc2420_local {
2285+ struct cc2420_platform_data *pdata;
2286+ struct spi_device *spi;
2287+ struct ieee802154_dev *dev;
2288+ u8 *buf;
2289+ struct mutex bmux;
2290+ int fifop_irq;
2291+ int sfd_irq;
2292+ struct work_struct fifop_irqwork;
2293+ struct work_struct sfd_irqwork;
2294+ spinlock_t lock;
2295+ unsigned irq_disabled:1;/* P:lock */
2296+ unsigned is_tx:1; /* P:lock */
2297+
2298+ struct completion tx_complete;
2299+};
2300+static int cc2420_get_status(struct cc2420_local *lp, u8 *status)
2301+{
2302+ int ret;
2303+ struct spi_message msg;
2304+ struct spi_transfer xfer = {
2305+ .len = 1,
2306+ .tx_buf = lp->buf,
2307+ .rx_buf = lp->buf,
2308+ };
2309+ spi_message_init(&msg);
2310+ spi_message_add_tail(&xfer, &msg);
2311+ mutex_lock(&lp->bmux);
2312+ lp->buf[0] = CC2420_WRITEREG(CC2420_SNOP);
2313+ dev_vdbg(&lp->spi->dev, "get status command buf[0] = %02x\n", lp->buf[0]);
2314+ ret = spi_sync(lp->spi, &msg);
2315+ if (!ret)
2316+ *status = lp->buf[0];
2317+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2318+ mutex_unlock(&lp->bmux);
2319+ return ret;
2320+
2321+}
2322+static int cc2420_cmd_strobe(struct cc2420_local *lp,
2323+ u8 addr)
2324+{
2325+ int ret;
2326+ u8 status = 0xf;
2327+ struct spi_message msg;
2328+ struct spi_transfer xfer = {
2329+ .len = 1,
2330+ .tx_buf = lp->buf,
2331+ .rx_buf = lp->buf,
2332+ };
2333+ spi_message_init(&msg);
2334+ spi_message_add_tail(&xfer, &msg);
2335+ mutex_lock(&lp->bmux);
2336+ lp->buf[0] = CC2420_WRITEREG(addr);
2337+ dev_vdbg(&lp->spi->dev, "cmd strobe buf[0] = %02x\n", lp->buf[0]);
2338+ ret = spi_sync(lp->spi, &msg);
2339+ if (!ret)
2340+ status = lp->buf[0];
2341+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2342+
2343+ mutex_unlock(&lp->bmux);
2344+
2345+ return ret;
2346+}
2347+
2348+static int cc2420_read_16_bit_reg(struct cc2420_local *lp,
2349+ u8 addr, u16 *data)
2350+{
2351+ int ret;
2352+ struct spi_message msg;
2353+ struct spi_transfer xfer = {
2354+ .len = 3,
2355+ .tx_buf = lp->buf,
2356+ .rx_buf = lp->buf,
2357+ };
2358+
2359+ spi_message_init(&msg);
2360+ spi_message_add_tail(&xfer, &msg);
2361+ mutex_lock(&lp->bmux);
2362+ lp->buf[0] = CC2420_READREG(addr);
2363+ dev_vdbg(&lp->spi->dev, "readreg addr buf[0] = %02x\n", lp->buf[0]);
2364+ ret = spi_sync(lp->spi, &msg);
2365+ dev_dbg(&lp->spi->dev, "status = %d\n", ret);
2366+ mutex_unlock(&lp->bmux);
2367+ dev_dbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2368+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2369+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2370+ if (!ret)
2371+ *data = ((u16) (lp->buf[1]) << 8) | lp->buf[2];
2372+ return ret;
2373+}
2374+
2375+static int cc2420_write_16_bit_reg_partial(struct cc2420_local *lp,
2376+ u8 addr, u16 data, u16 mask)
2377+{
2378+ int ret;
2379+ struct spi_message msg;
2380+ struct spi_transfer xfer = {
2381+ .len = 3,
2382+ .tx_buf = lp->buf,
2383+ .rx_buf = lp->buf,
2384+ };
2385+ dev_dbg(&lp->spi->dev, "data = %x\n", data);
2386+ dev_dbg(&lp->spi->dev, "mask = %x\n", mask);
2387+ spi_message_init(&msg);
2388+ spi_message_add_tail(&xfer, &msg);
2389+ mutex_lock(&lp->bmux);
2390+ lp->buf[0] = CC2420_READREG(addr);
2391+ dev_vdbg(&lp->spi->dev, "read addr buf[0] = %02x\n", lp->buf[0]);
2392+ ret = spi_sync(lp->spi, &msg);
2393+ if (ret)
2394+ goto err_ret;
2395+ dev_dbg(&lp->spi->dev, "read buf[0] = %02x\n", lp->buf[0]);
2396+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2397+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2398+
2399+ lp->buf[0] = CC2420_WRITEREG(addr);
2400+
2401+ lp->buf[1] &= ~(mask >> 8);
2402+ lp->buf[2] &= ~(mask & 0xFF);
2403+ lp->buf[1] |= (mask >> 8) & (data >> 8);
2404+ lp->buf[2] |= (mask & 0xFF) & (data & 0xFF);
2405+ dev_vdbg(&lp->spi->dev, "writereg addr buf[0] = %02x\n", lp->buf[0]);
2406+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2407+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2408+ ret = spi_sync(lp->spi, &msg);
2409+ if (ret)
2410+ goto err_ret;
2411+ dev_dbg(&lp->spi->dev, "return status buf[0] = %02x\n", lp->buf[0]);
2412+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2413+ dev_dbg(&lp->spi->dev, "buf[2] = %02x\n", lp->buf[2]);
2414+
2415+err_ret:
2416+ mutex_unlock(&lp->bmux);
2417+ return ret;
2418+}
2419+
2420+static int cc2420_channel(struct ieee802154_dev *dev, int page, int channel)
2421+{
2422+ struct cc2420_local *lp = dev->priv;
2423+ int ret;
2424+
2425+ might_sleep();
2426+ dev_dbg(&lp->spi->dev, "trying to set channel\n");
2427+
2428+ BUG_ON(page != 0);
2429+ BUG_ON(channel < CC2420_MIN_CHANNEL);
2430+ BUG_ON(channel > CC2420_MAX_CHANNEL);
2431+
2432+ ret = cc2420_write_16_bit_reg_partial(lp, CC2420_FSCTRL, 357 + 5*(channel - 11), CC2420_FREQ_MASK);
2433+
2434+ dev->phy->current_channel = channel;
2435+ return ret;
2436+}
2437+
2438+static int cc2420_write_ram(struct cc2420_local *lp, u16 addr, u8 len, u8 *data)
2439+{
2440+ int status;
2441+ struct spi_message msg;
2442+ struct spi_transfer xfer_head = {
2443+ .len = 2,
2444+ .tx_buf = lp->buf,
2445+ .rx_buf = lp->buf,
2446+ };
2447+ struct spi_transfer xfer_buf = {
2448+ .len = len,
2449+ .tx_buf = data,
2450+ };
2451+
2452+ mutex_lock(&lp->bmux);
2453+ lp->buf[0] = CC2420_RAMADDR(addr);
2454+ lp->buf[1] = CC2420_WRITERAM(CC2420_RAMBANK(addr));
2455+ dev_dbg(&lp->spi->dev, "write ram addr buf[0] = %02x\n", lp->buf[0]);
2456+ dev_dbg(&lp->spi->dev, "ram bank buf[1] = %02x\n", lp->buf[1]);
2457+
2458+ spi_message_init(&msg);
2459+ spi_message_add_tail(&xfer_head, &msg);
2460+ spi_message_add_tail(&xfer_buf, &msg);
2461+
2462+ status = spi_sync(lp->spi, &msg);
2463+ dev_dbg(&lp->spi->dev, "spi status = %d\n", status);
2464+ if (msg.status)
2465+ status = msg.status;
2466+ dev_dbg(&lp->spi->dev, "cc2420 status = %02x\n", lp->buf[0]);
2467+ dev_dbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2468+
2469+ mutex_unlock(&lp->bmux);
2470+ return status;
2471+}
2472+
2473+static int cc2420_write_txfifo(struct cc2420_local *lp, u8 *data, u8 len)
2474+{
2475+ int status;
2476+ /* Length byte must include FCS even if calculated in hardware */
2477+ int len_byte = len + 2;
2478+ struct spi_message msg;
2479+ struct spi_transfer xfer_head = {
2480+ .len = 1,
2481+ .tx_buf = lp->buf,
2482+ .rx_buf = lp->buf,
2483+ };
2484+ struct spi_transfer xfer_len = {
2485+ .len = 1,
2486+ .tx_buf = &len_byte,
2487+ };
2488+ struct spi_transfer xfer_buf = {
2489+ .len = len,
2490+ .tx_buf = data,
2491+ };
2492+
2493+ mutex_lock(&lp->bmux);
2494+ lp->buf[0] = CC2420_WRITEREG(CC2420_TXFIFO);
2495+ dev_vdbg(&lp->spi->dev, "TX_FIFO addr buf[0] = %02x\n", lp->buf[0]);
2496+
2497+ spi_message_init(&msg);
2498+ spi_message_add_tail(&xfer_head, &msg);
2499+ spi_message_add_tail(&xfer_len, &msg);
2500+ spi_message_add_tail(&xfer_buf, &msg);
2501+
2502+ status = spi_sync(lp->spi, &msg);
2503+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2504+ if (msg.status)
2505+ status = msg.status;
2506+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2507+ dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", lp->buf[0]);
2508+
2509+ mutex_unlock(&lp->bmux);
2510+ return status;
2511+}
2512+
2513+static int
2514+cc2420_read_rxfifo(struct cc2420_local *lp, u8 *data, u8 *len, u8 *lqi)
2515+{
2516+ int status;
2517+ struct spi_message msg;
2518+ struct spi_transfer xfer_head = {
2519+ .len = 2,
2520+ .tx_buf = lp->buf,
2521+ .rx_buf = lp->buf,
2522+ };
2523+ struct spi_transfer xfer_buf = {
2524+ .len = *len,
2525+ .rx_buf = data,
2526+ };
2527+
2528+ mutex_lock(&lp->bmux);
2529+ lp->buf[0] = CC2420_READREG(CC2420_RXFIFO);
2530+ lp->buf[1] = 0x00;
2531+ dev_vdbg(&lp->spi->dev, "read rxfifo buf[0] = %02x\n", lp->buf[0]);
2532+ dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", lp->buf[1]);
2533+ spi_message_init(&msg);
2534+ spi_message_add_tail(&xfer_head, &msg);
2535+ spi_message_add_tail(&xfer_buf, &msg);
2536+
2537+ status = spi_sync(lp->spi, &msg);
2538+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2539+ if (msg.status)
2540+ status = msg.status;
2541+ dev_vdbg(&lp->spi->dev, "status = %d\n", status);
2542+ dev_vdbg(&lp->spi->dev, "return status buf[0] = %02x\n", lp->buf[0]);
2543+ dev_vdbg(&lp->spi->dev, "length buf[1] = %02x\n", lp->buf[1]);
2544+
2545+ *lqi = data[lp->buf[1] - 1] & 0x7f;
2546+ *len = lp->buf[1]; /* it should be less than 130 */
2547+
2548+ mutex_unlock(&lp->bmux);
2549+
2550+ return status;
2551+}
2552+
2553+
2554+static int cc2420_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
2555+{
2556+ struct cc2420_local *lp = dev->priv;
2557+ int rc;
2558+ unsigned long flags;
2559+ u8 status = 0;
2560+
2561+ pr_debug("%s\n", __func__);
2562+
2563+ might_sleep();
2564+
2565+ rc = cc2420_cmd_strobe(lp, CC2420_SFLUSHTX);
2566+ if (rc)
2567+ goto err_rx;
2568+ rc = cc2420_write_txfifo(lp, skb->data, skb->len);
2569+ if (rc)
2570+ goto err_rx;
2571+
2572+ /* TODO: test CCA pin */
2573+
2574+ rc = cc2420_get_status(lp, &status);
2575+ if (rc)
2576+ goto err_rx;
2577+
2578+ if (status & CC2420_STATUS_TX_UNDERFLOW) {
2579+ dev_err(&lp->spi->dev, "cc2420 tx underflow!\n");
2580+ goto err_rx;
2581+ }
2582+
2583+ spin_lock_irqsave(&lp->lock, flags);
2584+ BUG_ON(lp->is_tx);
2585+ lp->is_tx = 1;
2586+ INIT_COMPLETION(lp->tx_complete);
2587+ spin_unlock_irqrestore(&lp->lock, flags);
2588+
2589+ rc = cc2420_cmd_strobe(lp, CC2420_STXONCCA);
2590+ if (rc)
2591+ goto err;
2592+
2593+ rc = wait_for_completion_interruptible(&lp->tx_complete);
2594+ if (rc < 0)
2595+ goto err;
2596+
2597+ cc2420_cmd_strobe(lp, CC2420_SFLUSHTX);
2598+ cc2420_cmd_strobe(lp, CC2420_SRXON);
2599+
2600+ return rc;
2601+
2602+err:
2603+ spin_lock_irqsave(&lp->lock, flags);
2604+ lp->is_tx = 0;
2605+ spin_unlock_irqrestore(&lp->lock, flags);
2606+err_rx:
2607+ cc2420_cmd_strobe(lp, CC2420_SFLUSHTX);
2608+ cc2420_cmd_strobe(lp, CC2420_SRXON);
2609+ return rc;
2610+}
2611+
2612+static int cc2420_rx(struct cc2420_local *lp)
2613+{
2614+ u8 len = 128;
2615+ u8 lqi = 0; /* link quality */
2616+ int rc;
2617+ struct sk_buff *skb;
2618+
2619+ skb = alloc_skb(len, GFP_KERNEL);
2620+ if (!skb)
2621+ return -ENOMEM;
2622+
2623+ rc = cc2420_read_rxfifo(lp, skb_put(skb, len), &len, &lqi);
2624+ if (len < 2) {
2625+ kfree_skb(skb);
2626+ return -EINVAL;
2627+ }
2628+
2629+ /* Clip last two bytes. When using hardware FCS they get replaced with
2630+ * correlation value, FCS flag and RSSI value */
2631+ skb_trim(skb, len-2);
2632+
2633+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
2634+
2635+ dev_dbg(&lp->spi->dev, "RXFIFO: %d %d %x\n", rc, len, lqi);
2636+
2637+ return 0;
2638+}
2639+
2640+static int
2641+cc2420_set_hw_addr_filt(struct ieee802154_dev *dev,
2642+ struct ieee802154_hw_addr_filt *filt,
2643+ unsigned long changed)
2644+{
2645+ struct cc2420_local *lp = dev->priv;
2646+ u16 reg;
2647+
2648+ might_sleep();
2649+
2650+ if (changed & IEEE802515_IEEEADDR_CHANGED)
2651+ cc2420_write_ram(lp, CC2420_RAM_IEEEADR,
2652+ IEEE802154_ALEN,
2653+ filt->ieee_addr);
2654+
2655+ if (changed & IEEE802515_SADDR_CHANGED) {
2656+ u8 short_addr[2];
2657+ short_addr[0] = filt->short_addr & 0xff;/* LSB */
2658+ short_addr[1] = filt->short_addr >> 8; /* MSB */
2659+ cc2420_write_ram(lp, CC2420_RAM_SHORTADR,
2660+ sizeof(short_addr),
2661+ short_addr);
2662+ }
2663+
2664+ if (changed & IEEE802515_PANID_CHANGED) {
2665+ u8 panid[2];
2666+ panid[0] = filt->pan_id & 0xff; /* LSB */
2667+ panid[1] = filt->pan_id >> 8; /* MSB */
2668+ cc2420_write_ram(lp, CC2420_RAM_PANID,
2669+ sizeof(panid),
2670+ panid);
2671+ }
2672+
2673+ if (changed & IEEE802515_PANC_CHANGED) {
2674+ cc2420_read_16_bit_reg(lp, CC2420_MDMCTRL0, &reg);
2675+ if (filt->pan_coord)
2676+ reg |= 1 << CC2420_MDMCTRL0_PANCRD;
2677+ else
2678+ reg &= ~(1 << CC2420_MDMCTRL0_PANCRD);
2679+ cc2420_write_16_bit_reg_partial(lp, CC2420_MDMCTRL0,
2680+ reg, 1 << CC2420_MDMCTRL0_PANCRD);
2681+ }
2682+
2683+ return 0;
2684+}
2685+
2686+static int cc2420_ed(struct ieee802154_dev *dev, u8 *level)
2687+{
2688+ struct cc2420_local *lp = dev->priv;
2689+ u16 rssi;
2690+ int ret;
2691+ dev_dbg(&lp->spi->dev, "ed called\n");
2692+
2693+ ret = cc2420_read_16_bit_reg(lp, CC2420_RSSI, &rssi);
2694+ if (ret)
2695+ return ret;
2696+
2697+ /* P = RSSI_VAL + RSSI_OFFSET[dBm] */
2698+ *level = (rssi & CC2420_RSSI_MASK) + RSSI_OFFSET;
2699+ return ret;
2700+}
2701+
2702+static int cc2420_start(struct ieee802154_dev *dev)
2703+{
2704+ return cc2420_cmd_strobe(dev->priv, CC2420_SRXON);
2705+}
2706+
2707+static void cc2420_stop(struct ieee802154_dev *dev)
2708+{
2709+ cc2420_cmd_strobe(dev->priv, CC2420_SRFOFF);
2710+}
2711+
2712+static struct ieee802154_ops cc2420_ops = {
2713+ .owner = THIS_MODULE,
2714+ .xmit = cc2420_tx,
2715+ .ed = cc2420_ed,
2716+ .start = cc2420_start,
2717+ .stop = cc2420_stop,
2718+ .set_channel = cc2420_channel,
2719+ .set_hw_addr_filt = cc2420_set_hw_addr_filt,
2720+};
2721+
2722+static int cc2420_register(struct cc2420_local *lp)
2723+{
2724+ int ret = -ENOMEM;
2725+ lp->dev = ieee802154_alloc_device(sizeof(*lp), &cc2420_ops);
2726+ if (!lp->dev)
2727+ goto err_ret;
2728+
2729+ lp->dev->priv = lp;
2730+ lp->dev->parent = &lp->spi->dev;
2731+ //look this up.
2732+ lp->dev->extra_tx_headroom = 0;
2733+ //and this
2734+ //lp->dev->channel_mask = 0x7ff;
2735+ //and more.
2736+
2737+ /* We do support only 2.4 Ghz */
2738+ lp->dev->phy->channels_supported[0] = 0x7FFF800;
2739+ lp->dev->flags = IEEE802154_HW_OMIT_CKSUM;
2740+
2741+ dev_dbg(&lp->spi->dev, "registered cc2420\n");
2742+ ret = ieee802154_register_device(lp->dev);
2743+ if (ret)
2744+ goto err_free_device;
2745+
2746+ return 0;
2747+err_free_device:
2748+ ieee802154_free_device(lp->dev);
2749+err_ret:
2750+ return ret;
2751+}
2752+
2753+static void cc2420_unregister(struct cc2420_local *lp)
2754+{
2755+ ieee802154_unregister_device(lp->dev);
2756+ //check this is needed
2757+ ieee802154_free_device(lp->dev);
2758+}
2759+
2760+static irqreturn_t cc2420_isr(int irq, void *data)
2761+{
2762+ struct cc2420_local *lp = data;
2763+
2764+ spin_lock(&lp->lock);
2765+ if (!lp->irq_disabled) {
2766+ disable_irq_nosync(irq);
2767+ lp->irq_disabled = 1;
2768+ }
2769+ spin_unlock(&lp->lock);
2770+
2771+ if (irq == lp->sfd_irq)
2772+ schedule_work(&lp->sfd_irqwork);
2773+
2774+ if (irq == lp->fifop_irq)
2775+ schedule_work(&lp->fifop_irqwork);
2776+
2777+ return IRQ_HANDLED;
2778+}
2779+
2780+static void cc2420_fifop_irqwork(struct work_struct *work)
2781+{
2782+ struct cc2420_local *lp
2783+ = container_of(work, struct cc2420_local, fifop_irqwork);
2784+ unsigned long flags;
2785+
2786+ dev_dbg(&lp->spi->dev, "fifop interrupt received\n");
2787+
2788+ if (gpio_get_value(lp->pdata->fifo))
2789+ cc2420_rx(lp);
2790+ else
2791+ dev_err(&lp->spi->dev, "rxfifo overflow\n");
2792+
2793+ cc2420_cmd_strobe(lp, CC2420_SFLUSHRX);
2794+ cc2420_cmd_strobe(lp, CC2420_SFLUSHRX);
2795+
2796+ spin_lock_irqsave(&lp->lock, flags);
2797+ if (lp->irq_disabled) {
2798+ lp->irq_disabled = 0;
2799+ enable_irq(lp->fifop_irq);
2800+ }
2801+ spin_unlock_irqrestore(&lp->lock, flags);
2802+}
2803+
2804+static void cc2420_sfd_irqwork(struct work_struct *work)
2805+{
2806+ struct cc2420_local *lp
2807+ = container_of(work, struct cc2420_local, sfd_irqwork);
2808+ unsigned long flags;
2809+
2810+ dev_dbg(&lp->spi->dev, "sfd interrupt received\n");
2811+
2812+ spin_lock_irqsave(&lp->lock, flags);
2813+ if (lp->is_tx) {
2814+ lp->is_tx = 0;
2815+ spin_unlock_irqrestore(&lp->lock, flags);
2816+ complete(&lp->tx_complete);
2817+ } else {
2818+ spin_unlock_irqrestore(&lp->lock, flags);
2819+ }
2820+
2821+ spin_lock_irqsave(&lp->lock, flags);
2822+ if (lp->irq_disabled) {
2823+ lp->irq_disabled = 0;
2824+ enable_irq(lp->sfd_irq);
2825+ }
2826+ spin_unlock_irqrestore(&lp->lock, flags);
2827+}
2828+
2829+static int cc2420_hw_init(struct cc2420_local *lp)
2830+{
2831+ int ret;
2832+ u16 state;
2833+ u8 status = 0xff;
2834+ int timeout = 500; /* 500us delay */
2835+ ret = cc2420_read_16_bit_reg(lp, CC2420_FSMSTATE, &state);
2836+ if (ret)
2837+ goto error_ret;
2838+ /* reset has occured prior to this, so there should be no other option */
2839+ if (state != STATE_PDOWN) {
2840+ ret = -EINVAL;
2841+ goto error_ret;
2842+ }
2843+ ret = cc2420_cmd_strobe(lp, CC2420_SXOSCON);
2844+ if (ret)
2845+ goto error_ret;
2846+
2847+ do {
2848+ ret = cc2420_get_status(lp, &status);
2849+ if (ret)
2850+ goto error_ret;
2851+ if (timeout-- <= 0) {
2852+ dev_err(&lp->spi->dev, "oscillator start failed!\n");
2853+ return ret;
2854+ }
2855+ udelay(1);
2856+ } while (!(status & CC2420_STATUS_XOSC16M_STABLE));
2857+
2858+ dev_info(&lp->spi->dev, "oscillator succesfully brought up\n");
2859+
2860+ return 0;
2861+error_ret:
2862+ return ret;
2863+}
2864+
2865+static int __devinit cc2420_probe(struct spi_device *spi)
2866+{
2867+ int ret;
2868+ u16 manidl, manidh;
2869+ struct cc2420_local *lp = kzalloc(sizeof *lp, GFP_KERNEL);
2870+ if (!lp) {
2871+ ret = -ENOMEM;
2872+ goto error_ret;
2873+ }
2874+
2875+ lp->pdata = spi->dev.platform_data;
2876+ if (!lp->pdata) {
2877+ dev_err(&spi->dev, "no platform data\n");
2878+ ret = -EINVAL;
2879+ goto err_free_local;
2880+ }
2881+ spi_set_drvdata(spi, lp);
2882+ mutex_init(&lp->bmux);
2883+ INIT_WORK(&lp->fifop_irqwork, cc2420_fifop_irqwork);
2884+ INIT_WORK(&lp->sfd_irqwork, cc2420_sfd_irqwork);
2885+ spin_lock_init(&lp->lock);
2886+ init_completion(&lp->tx_complete);
2887+
2888+ lp->spi = spi;
2889+ lp->buf = kmalloc(3*sizeof *lp->buf, GFP_KERNEL);
2890+ if (!lp->buf) {
2891+ ret = -ENOMEM;
2892+ goto err_free_local;
2893+ }
2894+
2895+ /* Request all the gpio's */
2896+ ret = gpio_request(lp->pdata->fifo, "fifo");
2897+ if (ret)
2898+ goto err_free_buf;
2899+ ret = gpio_request(lp->pdata->cca, "cca");
2900+ if (ret)
2901+ goto err_free_gpio_fifo;
2902+#if 0
2903+ /* This is causing problems as fifop is gpio 0 ? */
2904+ ret = gpio_request(lp->pdata->fifop, "fifop");
2905+ if (ret)
2906+ goto err_free_gpio_cca;
2907+#endif
2908+ ret = gpio_request(lp->pdata->sfd, "sfd");
2909+ if (ret)
2910+ goto err_free_gpio_fifop;
2911+ ret = gpio_request(lp->pdata->reset, "reset");
2912+ if (ret)
2913+ goto err_free_gpio_sfd;
2914+ ret = gpio_request(lp->pdata->vreg, "vreg");
2915+ if (ret)
2916+ goto err_free_gpio_reset;
2917+ /* Configure the gpios appropriately */
2918+
2919+ /* Enable the voltage regulator */
2920+ ret = gpio_direction_output(lp->pdata->vreg, 1);
2921+ if (ret)
2922+ goto err_free_gpio_reset;
2923+ udelay(600); /* Time for regulator to power up */
2924+ /* Toggle the reset */
2925+ ret = gpio_direction_output(lp->pdata->reset, 0);
2926+ if (ret)
2927+ goto err_disable_vreg;
2928+ udelay(10); /* no idea how long this should be? */
2929+ ret = gpio_direction_output(lp->pdata->reset, 1);
2930+ if (ret)
2931+ goto err_disable_vreg;
2932+ udelay(10);
2933+
2934+ ret = gpio_direction_input(lp->pdata->cca);
2935+ if (ret)
2936+ goto err_disable_vreg;
2937+ ret = gpio_direction_input(lp->pdata->fifo);
2938+ if (ret)
2939+ goto err_disable_vreg;
2940+ ret = gpio_direction_input(lp->pdata->fifop);
2941+ if (ret)
2942+ goto err_disable_vreg;
2943+ ret = gpio_direction_input(lp->pdata->sfd);
2944+ if (ret)
2945+ goto err_disable_vreg;
2946+
2947+
2948+ /* Check this is actually a cc2420 */
2949+ ret = cc2420_read_16_bit_reg(lp, CC2420_MANFIDL, &manidl);
2950+ if (ret)
2951+ goto err_free_gpio_vreg;
2952+ ret = cc2420_read_16_bit_reg(lp, CC2420_MANFIDH, &manidh);
2953+ if (ret)
2954+ goto err_free_gpio_vreg;
2955+ if (manidh != CC2420_MANFIDHIGH || manidl != CC2420_MANFIDLOW) {
2956+ dev_err(&spi->dev, "Incorrect manufacturer id %x%x\n", manidh, manidl);
2957+ ret = -ENODEV;
2958+ goto err_free_gpio_vreg;
2959+ }
2960+ /* TODO: make it more readable */
2961+ dev_info(&lp->spi->dev, "Found Chipcon CC2420\n");
2962+ dev_info(&lp->spi->dev, "Manufacturer ID:%x Version:%x Partnum:%x\n",
2963+ manidl & 0x0FFF, manidh >> 12, manidl >> 12);
2964+
2965+ ret = cc2420_hw_init(lp);
2966+ if (ret)
2967+ goto err_disable_vreg;
2968+
2969+ lp->fifop_irq = gpio_to_irq(lp->pdata->fifop);
2970+ lp->sfd_irq = gpio_to_irq(lp->pdata->sfd);
2971+
2972+ ret = request_irq(lp->fifop_irq,
2973+ cc2420_isr,
2974+ IRQF_TRIGGER_RISING | IRQF_SHARED,
2975+ dev_name(&spi->dev),
2976+ lp);
2977+ if (ret) {
2978+ dev_err(&spi->dev, "could not get fifop irq?\n");
2979+ goto err_free_fifop_irq;
2980+ }
2981+
2982+ ret = request_irq(lp->sfd_irq,
2983+ cc2420_isr,
2984+ IRQF_TRIGGER_FALLING,
2985+ dev_name(&spi->dev),
2986+ lp);
2987+ if (ret) {
2988+ dev_err(&spi->dev, "could not get sfd irq?\n");
2989+ goto err_free_sfd_irq;
2990+ }
2991+
2992+ dev_info(&lp->spi->dev, "Set fifo threshold to 127\n");
2993+ cc2420_write_16_bit_reg_partial(lp, CC2420_IOCFG0, 127, CC2420_FIFOP_THR_MASK);
2994+ ret = cc2420_register(lp);
2995+ if (ret)
2996+ goto err_free_sfd_irq;
2997+
2998+ return 0;
2999+err_free_sfd_irq:
3000+ free_irq(lp->sfd_irq, lp);
3001+err_free_fifop_irq:
3002+ free_irq(lp->fifop_irq, lp);
3003+err_disable_vreg:
3004+ gpio_set_value(lp->pdata->vreg, 0);
3005+err_free_gpio_vreg:
3006+ gpio_free(lp->pdata->vreg);
3007+err_free_gpio_reset:
3008+ gpio_free(lp->pdata->reset);
3009+err_free_gpio_sfd:
3010+ gpio_free(lp->pdata->sfd);
3011+err_free_gpio_fifop:
3012+ gpio_free(lp->pdata->fifop);
3013+//err_free_gpio_cca:
3014+// gpio_free(lp->pdata->cca);
3015+err_free_gpio_fifo:
3016+ gpio_free(lp->pdata->fifo);
3017+err_free_buf:
3018+ kfree(lp->buf);
3019+err_free_local:
3020+ kfree(lp);
3021+error_ret:
3022+ return ret;
3023+}
3024+
3025+static int __devexit cc2420_remove(struct spi_device *spi)
3026+{
3027+ struct cc2420_local *lp = spi_get_drvdata(spi);
3028+
3029+ cc2420_unregister(lp);
3030+ free_irq(lp->fifop_irq, lp);
3031+ free_irq(lp->sfd_irq, lp);
3032+ flush_work(&lp->fifop_irqwork);
3033+ flush_work(&lp->sfd_irqwork);
3034+ gpio_free(lp->pdata->vreg);
3035+ gpio_free(lp->pdata->reset);
3036+ gpio_free(lp->pdata->sfd);
3037+ gpio_free(lp->pdata->fifop);
3038+ gpio_free(lp->pdata->cca);
3039+ gpio_free(lp->pdata->fifo);
3040+ kfree(lp->buf);
3041+ kfree(lp);
3042+
3043+ return 0;
3044+}
3045+
3046+static struct spi_driver cc2420_driver = {
3047+ .driver = {
3048+ .name = "cc2420",
3049+ .owner = THIS_MODULE,
3050+ },
3051+ .probe = cc2420_probe,
3052+ .remove = __devexit_p(cc2420_remove),
3053+};
3054+
3055+static int __init cc2420_init(void)
3056+{
3057+ return spi_register_driver(&cc2420_driver);
3058+}
3059+module_init(cc2420_init);
3060+
3061+static void __exit cc2420_exit(void)
3062+{
3063+ spi_unregister_driver(&cc2420_driver);
3064+}
3065+module_exit(cc2420_exit);
3066+MODULE_LICENSE("GPL v2");
3067diff --git a/drivers/ieee802154/fakelb.c b/drivers/ieee802154/fakelb.c
3068new file mode 100644
3069index 0000000..ae6e53f
3070--- /dev/null
3071@@ -0,0 +1,311 @@
3072+/*
3073+ * Loopback IEEE 802.15.4 interface
3074+ *
3075+ * Copyright 2007, 2008 Siemens AG
3076+ *
3077+ * This program is free software; you can redistribute it and/or modify
3078+ * it under the terms of the GNU General Public License version 2
3079+ * as published by the Free Software Foundation.
3080+ *
3081+ * This program is distributed in the hope that it will be useful,
3082+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3083+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3084+ * GNU General Public License for more details.
3085+ *
3086+ * You should have received a copy of the GNU General Public License along
3087+ * with this program; if not, write to the Free Software Foundation, Inc.,
3088+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3089+ *
3090+ * Written by:
3091+ * Sergey Lapin <slapin@ossfans.org>
3092+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
3093+ */
3094+
3095+#include <linux/module.h>
3096+#include <linux/timer.h>
3097+#include <linux/platform_device.h>
3098+#include <linux/netdevice.h>
3099+#include <linux/spinlock.h>
3100+#include <net/mac802154.h>
3101+#include <net/wpan-phy.h>
3102+
3103+struct fake_dev_priv {
3104+ struct ieee802154_dev *dev;
3105+
3106+ struct list_head list;
3107+ struct fake_priv *fake;
3108+
3109+ unsigned int working:1;
3110+};
3111+
3112+struct fake_priv {
3113+ struct list_head list;
3114+ rwlock_t lock;
3115+};
3116+
3117+static int
3118+hw_ed(struct ieee802154_dev *dev, u8 *level)
3119+{
3120+ pr_debug("%s\n", __func__);
3121+ might_sleep();
3122+ BUG_ON(!level);
3123+ *level = 0xbe;
3124+ return 0;
3125+}
3126+
3127+static int
3128+hw_channel(struct ieee802154_dev *dev, int page, int channel)
3129+{
3130+ pr_debug("%s %d\n", __func__, channel);
3131+ might_sleep();
3132+ dev->phy->current_page = page;
3133+ dev->phy->current_channel = channel;
3134+ return 0;
3135+}
3136+
3137+static void
3138+hw_deliver(struct fake_dev_priv *priv, struct sk_buff *skb)
3139+{
3140+ struct sk_buff *newskb;
3141+
3142+ if (!priv->working)
3143+ return;
3144+
3145+ newskb = pskb_copy(skb, GFP_ATOMIC);
3146+
3147+ ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc);
3148+}
3149+
3150+static int
3151+hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
3152+{
3153+ struct fake_dev_priv *priv = dev->priv;
3154+ struct fake_priv *fake = priv->fake;
3155+
3156+ might_sleep();
3157+
3158+ read_lock_bh(&fake->lock);
3159+ if (priv->list.next == priv->list.prev) {
3160+ /* we are the only one device */
3161+ hw_deliver(priv, skb);
3162+ } else {
3163+ struct fake_dev_priv *dp;
3164+ list_for_each_entry(dp, &priv->fake->list, list)
3165+ if (dp != priv &&
3166+ dp->dev->phy->current_channel ==
3167+ priv->dev->phy->current_channel)
3168+ hw_deliver(dp, skb);
3169+ }
3170+ read_unlock_bh(&fake->lock);
3171+
3172+ return 0;
3173+}
3174+
3175+static int
3176+hw_start(struct ieee802154_dev *dev) {
3177+ struct fake_dev_priv *priv = dev->priv;
3178+
3179+ if (priv->working)
3180+ return -EBUSY;
3181+
3182+ priv->working = 1;
3183+
3184+ return 0;
3185+}
3186+
3187+static void
3188+hw_stop(struct ieee802154_dev *dev) {
3189+ struct fake_dev_priv *priv = dev->priv;
3190+
3191+ priv->working = 0;
3192+}
3193+
3194+static struct ieee802154_ops fake_ops = {
3195+ .owner = THIS_MODULE,
3196+ .xmit = hw_xmit,
3197+ .ed = hw_ed,
3198+ .set_channel = hw_channel,
3199+ .start = hw_start,
3200+ .stop = hw_stop,
3201+};
3202+
3203+static int ieee802154fake_add_priv(struct device *dev, struct fake_priv *fake)
3204+{
3205+ struct fake_dev_priv *priv;
3206+ int err = -ENOMEM;
3207+ struct ieee802154_dev *ieee;
3208+
3209+ ieee = ieee802154_alloc_device(sizeof(*priv), &fake_ops);
3210+ if (!dev)
3211+ goto err_alloc_dev;
3212+
3213+ priv = ieee->priv;
3214+ priv->dev = ieee;
3215+
3216+ /* 868 MHz BPSK 802.15.4-2003 */
3217+ ieee->phy->channels_supported[0] |= 1;
3218+ /* 915 MHz BPSK 802.15.4-2003 */
3219+ ieee->phy->channels_supported[0] |= 0x7fe;
3220+ /* 2.4 GHz O-QPSK 802.15.4-2003 */
3221+ ieee->phy->channels_supported[0] |= 0x7FFF800;
3222+ /* 868 MHz ASK 802.15.4-2006 */
3223+ ieee->phy->channels_supported[1] |= 1;
3224+ /* 915 MHz ASK 802.15.4-2006 */
3225+ ieee->phy->channels_supported[1] |= 0x7fe;
3226+ /* 868 MHz O-QPSK 802.15.4-2006 */
3227+ ieee->phy->channels_supported[2] |= 1;
3228+ /* 915 MHz O-QPSK 802.15.4-2006 */
3229+ ieee->phy->channels_supported[2] |= 0x7fe;
3230+ /* 2.4 GHz CSS 802.15.4a-2007 */
3231+ ieee->phy->channels_supported[3] |= 0x3fff;
3232+ /* UWB Sub-gigahertz 802.15.4a-2007 */
3233+ ieee->phy->channels_supported[4] |= 1;
3234+ /* UWB Low band 802.15.4a-2007 */
3235+ ieee->phy->channels_supported[4] |= 0x1e;
3236+ /* UWB High band 802.15.4a-2007 */
3237+ ieee->phy->channels_supported[4] |= 0xffe0;
3238+ /* 750 MHz O-QPSK 802.15.4c-2009 */
3239+ ieee->phy->channels_supported[5] |= 0xf;
3240+ /* 750 MHz MPSK 802.15.4c-2009 */
3241+ ieee->phy->channels_supported[5] |= 0xf0;
3242+ /* 950 MHz BPSK 802.15.4d-2009 */
3243+ ieee->phy->channels_supported[6] |= 0x3ff;
3244+ /* 950 MHz GFSK 802.15.4d-2009 */
3245+ ieee->phy->channels_supported[6] |= 0x3ffc00;
3246+
3247+
3248+ INIT_LIST_HEAD(&priv->list);
3249+ priv->fake = fake;
3250+
3251+ ieee->parent = dev;
3252+
3253+ err = ieee802154_register_device(ieee);
3254+ if (err)
3255+ goto err_reg;
3256+
3257+ write_lock_bh(&fake->lock);
3258+ list_add_tail(&priv->list, &fake->list);
3259+ write_unlock_bh(&fake->lock);
3260+
3261+ return 0;
3262+
3263+err_reg:
3264+ ieee802154_free_device(priv->dev);
3265+err_alloc_dev:
3266+ return err;
3267+}
3268+
3269+static void ieee802154fake_del_priv(struct fake_dev_priv *priv)
3270+{
3271+ write_lock_bh(&priv->fake->lock);
3272+ list_del(&priv->list);
3273+ write_unlock_bh(&priv->fake->lock);
3274+
3275+ ieee802154_unregister_device(priv->dev);
3276+ ieee802154_free_device(priv->dev);
3277+}
3278+
3279+static ssize_t
3280+adddev_store(struct device *dev, struct device_attribute *attr,
3281+ const char *buf, size_t n)
3282+{
3283+ struct platform_device *pdev = to_platform_device(dev);
3284+ struct fake_priv *priv = platform_get_drvdata(pdev);
3285+ int err;
3286+
3287+ err = ieee802154fake_add_priv(dev, priv);
3288+ if (err)
3289+ return err;
3290+ return n;
3291+}
3292+
3293+static DEVICE_ATTR(adddev, 0200, NULL, adddev_store);
3294+
3295+static struct attribute *fake_attrs[] = {
3296+ &dev_attr_adddev.attr,
3297+ NULL,
3298+};
3299+
3300+static struct attribute_group fake_group = {
3301+ .name = NULL /* fake */,
3302+ .attrs = fake_attrs,
3303+};
3304+
3305+
3306+static int __devinit ieee802154fake_probe(struct platform_device *pdev)
3307+{
3308+ struct fake_priv *priv;
3309+ struct fake_dev_priv *dp;
3310+
3311+ int err = -ENOMEM;
3312+ priv = kzalloc(sizeof(struct fake_priv), GFP_KERNEL);
3313+ if (!priv)
3314+ goto err_alloc;
3315+
3316+ INIT_LIST_HEAD(&priv->list);
3317+ rwlock_init(&priv->lock);
3318+
3319+ err = sysfs_create_group(&pdev->dev.kobj, &fake_group);
3320+ if (err)
3321+ goto err_grp;
3322+
3323+ err = ieee802154fake_add_priv(&pdev->dev, priv);
3324+ if (err < 0)
3325+ goto err_slave;
3326+
3327+ platform_set_drvdata(pdev, priv);
3328+ dev_info(&pdev->dev, "Added ieee802154 hardware\n");
3329+ return 0;
3330+
3331+err_slave:
3332+ list_for_each_entry(dp, &priv->list, list)
3333+ ieee802154fake_del_priv(dp);
3334+ sysfs_remove_group(&pdev->dev.kobj, &fake_group);
3335+err_grp:
3336+ kfree(priv);
3337+err_alloc:
3338+ return err;
3339+}
3340+
3341+static int __devexit ieee802154fake_remove(struct platform_device *pdev)
3342+{
3343+ struct fake_priv *priv = platform_get_drvdata(pdev);
3344+ struct fake_dev_priv *dp, *temp;
3345+
3346+ list_for_each_entry_safe(dp, temp, &priv->list, list)
3347+ ieee802154fake_del_priv(dp);
3348+ sysfs_remove_group(&pdev->dev.kobj, &fake_group);
3349+ kfree(priv);
3350+ return 0;
3351+}
3352+
3353+static struct platform_device *ieee802154fake_dev;
3354+
3355+static struct platform_driver ieee802154fake_driver = {
3356+ .probe = ieee802154fake_probe,
3357+ .remove = __devexit_p(ieee802154fake_remove),
3358+ .driver = {
3359+ .name = "ieee802154fakelb",
3360+ .owner = THIS_MODULE,
3361+ },
3362+};
3363+
3364+static __init int fake_init(void)
3365+{
3366+ ieee802154fake_dev = platform_device_register_simple(
3367+ "ieee802154fakelb", -1, NULL, 0);
3368+ return platform_driver_register(&ieee802154fake_driver);
3369+}
3370+
3371+static __exit void fake_exit(void)
3372+{
3373+ platform_driver_unregister(&ieee802154fake_driver);
3374+ platform_device_unregister(ieee802154fake_dev);
3375+}
3376+
3377+module_init(fake_init);
3378+module_exit(fake_exit);
3379+MODULE_LICENSE("GPL");
3380+MODULE_AUTHOR("Dmitry Eremin-Solenikov, Sergey Lapin");
3381+
3382+
3383diff --git a/drivers/ieee802154/serial.c b/drivers/ieee802154/serial.c
3384new file mode 100644
3385index 0000000..6981d0e
3386--- /dev/null
3387@@ -0,0 +1,1047 @@
3388+/*
3389+ * ZigBee TTY line discipline.
3390+ *
3391+ * Provides interface between ZigBee stack and IEEE 802.15.4 compatible
3392+ * firmware over serial line. Communication protocol is described below.
3393+ *
3394+ * Copyright (C) 2007, 2008, 2009 Siemens AG
3395+ *
3396+ * This program is free software; you can redistribute it and/or modify
3397+ * it under the terms of the GNU General Public License version 2
3398+ * as published by the Free Software Foundation.
3399+ *
3400+ * This program is distributed in the hope that it will be useful,
3401+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3402+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3403+ * GNU General Public License for more details.
3404+ *
3405+ * You should have received a copy of the GNU General Public License along
3406+ * with this program; if not, write to the Free Software Foundation, Inc.,
3407+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3408+ *
3409+ * Written by:
3410+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
3411+ * Maxim Osipov <maxim.osipov@siemens.com>
3412+ * Sergey Lapin <slapin@ossfans.org>
3413+ */
3414+
3415+#include <linux/module.h>
3416+#include <linux/kernel.h>
3417+#include <linux/completion.h>
3418+#include <linux/tty.h>
3419+#include <linux/skbuff.h>
3420+#include <linux/sched.h>
3421+#include <net/mac802154.h>
3422+#include <net/wpan-phy.h>
3423+
3424+
3425+/* NOTE: be sure to use here the same values as in the firmware */
3426+#define START_BYTE1 'z'
3427+#define START_BYTE2 'b'
3428+#define MAX_DATA_SIZE 127
3429+
3430+#define IDLE_MODE 0x00
3431+#define RX_MODE 0x02
3432+#define TX_MODE 0x03
3433+#define FORCE_TRX_OFF 0xF0
3434+
3435+#define STATUS_SUCCESS 0
3436+#define STATUS_RX_ON 1
3437+#define STATUS_TX_ON 2
3438+#define STATUS_TRX_OFF 3
3439+#define STATUS_IDLE 4
3440+#define STATUS_BUSY 5
3441+#define STATUS_BUSY_RX 6
3442+#define STATUS_BUSY_TX 7
3443+#define STATUS_ERR 8
3444+
3445+#define STATUS_WAIT ((u8) -1) /* waiting for the answer */
3446+
3447+/* We re-use PPP ioctl for our purposes */
3448+#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
3449+
3450+/*
3451+ * The following messages are used to control ZigBee firmware.
3452+ * All communication has request/response format,
3453+ * except of asynchronous incoming data stream (DATA_RECV_* messages).
3454+ */
3455+enum {
3456+ NO_ID = 0, /* means no pending id */
3457+
3458+ /* Driver to Firmware */
3459+ CMD_OPEN = 0x01, /* u8 id */
3460+ CMD_CLOSE = 0x02, /* u8 id */
3461+ CMD_SET_CHANNEL = 0x04, /* u8 id, u8 channel */
3462+ CMD_ED = 0x05, /* u8 id */
3463+ CMD_CCA = 0x06, /* u8 id */
3464+ CMD_SET_STATE = 0x07, /* u8 id, u8 flag */
3465+ DATA_XMIT_BLOCK = 0x09, /* u8 id, u8 len, u8 data[len] */
3466+ RESP_RECV_BLOCK = 0x0b, /* u8 id, u8 status */
3467+ CMD_ADDRESS = 0x0d, /* u8 id */
3468+
3469+ /* Firmware to Driver */
3470+ RESP_OPEN = 0x81, /* u8 id, u8 status */
3471+ RESP_CLOSE = 0x82, /* u8 id, u8 status */
3472+ RESP_SET_CHANNEL = 0x84, /* u8 id, u8 status */
3473+ RESP_ED = 0x85, /* u8 id, u8 status, u8 level */
3474+ RESP_CCA = 0x86, /* u8 id, u8 status */
3475+ RESP_SET_STATE = 0x87, /* u8 id, u8 status */
3476+ RESP_XMIT_BLOCK = 0x89, /* u8 id, u8 status */
3477+ DATA_RECV_BLOCK = 0x8b, /* u8 id, u8 lq, u8 len, u8 data[len] */
3478+ RESP_ADDRESS = 0x8d, /* u8 id, u8 status, u8 u8 u8 u8 u8 u8 u8 u8 address */
3479+};
3480+
3481+enum {
3482+ STATE_WAIT_START1,
3483+ STATE_WAIT_START2,
3484+ STATE_WAIT_COMMAND,
3485+ STATE_WAIT_PARAM1,
3486+ STATE_WAIT_PARAM2,
3487+ STATE_WAIT_DATA
3488+};
3489+
3490+struct zb_device {
3491+ /* Relative devices */
3492+ struct tty_struct *tty;
3493+ struct ieee802154_dev *dev;
3494+
3495+ /* locks the ldisc for the command */
3496+ struct mutex mutex;
3497+
3498+ /* command completition */
3499+ wait_queue_head_t wq;
3500+ u8 status;
3501+ u8 ed;
3502+
3503+ /* Internal state */
3504+ struct completion open_done;
3505+ unsigned char opened;
3506+ u8 pending_id;
3507+ unsigned int pending_size;
3508+ u8 *pending_data;
3509+ /* FIXME: WE NEED LOCKING!!! */
3510+
3511+ /* Command (rx) processing */
3512+ int state;
3513+ unsigned char id;
3514+ unsigned char param1;
3515+ unsigned char param2;
3516+ unsigned char index;
3517+ unsigned char data[MAX_DATA_SIZE];
3518+};
3519+
3520+/*****************************************************************************
3521+ * ZigBee serial device protocol handling
3522+ *****************************************************************************/
3523+static int _open_dev(struct zb_device *zbdev);
3524+
3525+static int
3526+_send_pending_data(struct zb_device *zbdev)
3527+{
3528+ struct tty_struct *tty;
3529+
3530+ BUG_ON(!zbdev);
3531+ tty = zbdev->tty;
3532+ if (!tty)
3533+ return -ENODEV;
3534+
3535+ zbdev->status = STATUS_WAIT;
3536+
3537+ /* Debug info */
3538+ printk(KERN_INFO "%s, %d bytes\n", __func__,
3539+ zbdev->pending_size);
3540+#ifdef DEBUG
3541+ print_hex_dump_bytes("send_pending_data ", DUMP_PREFIX_NONE,
3542+ zbdev->pending_data, zbdev->pending_size);
3543+#endif
3544+
3545+ if (tty->driver->ops->write(tty, zbdev->pending_data,
3546+ zbdev->pending_size) != zbdev->pending_size) {
3547+ printk(KERN_ERR "%s: device write failed\n", __func__);
3548+ return -1;
3549+ }
3550+
3551+ return 0;
3552+}
3553+
3554+static int
3555+send_cmd(struct zb_device *zbdev, u8 id)
3556+{
3557+ u8 len = 0;
3558+ /* 4 because of 2 start bytes, id and optional extra */
3559+ u8 buf[4];
3560+
3561+ /* Check arguments */
3562+ BUG_ON(!zbdev);
3563+
3564+ if (!zbdev->opened) {
3565+ if (!_open_dev(zbdev))
3566+ return -EAGAIN;
3567+ }
3568+
3569+ pr_debug("%s(): id = %u\n", __func__, id);
3570+ if (zbdev->pending_size) {
3571+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3572+ __func__, zbdev->pending_id);
3573+ BUG();
3574+ }
3575+
3576+ /* Prepare a message */
3577+ buf[len++] = START_BYTE1;
3578+ buf[len++] = START_BYTE2;
3579+ buf[len++] = id;
3580+
3581+ zbdev->pending_id = id;
3582+ zbdev->pending_size = len;
3583+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3584+ if (!zbdev->pending_data) {
3585+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3586+ zbdev->pending_id = 0;
3587+ zbdev->pending_size = 0;
3588+ return -ENOMEM;
3589+ }
3590+ memcpy(zbdev->pending_data, buf, len);
3591+
3592+ return _send_pending_data(zbdev);
3593+}
3594+
3595+static int
3596+send_cmd2(struct zb_device *zbdev, u8 id, u8 extra)
3597+{
3598+ u8 len = 0;
3599+ /* 4 because of 2 start bytes, id and optional extra */
3600+ u8 buf[4];
3601+
3602+ /* Check arguments */
3603+ BUG_ON(!zbdev);
3604+
3605+ if (!zbdev->opened) {
3606+ if (!_open_dev(zbdev))
3607+ return -EAGAIN;
3608+ }
3609+
3610+ pr_debug("%s(): id = %u\n", __func__, id);
3611+ if (zbdev->pending_size) {
3612+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3613+ __func__, zbdev->pending_id);
3614+ BUG();
3615+ }
3616+
3617+ /* Prepare a message */
3618+ buf[len++] = START_BYTE1;
3619+ buf[len++] = START_BYTE2;
3620+ buf[len++] = id;
3621+ buf[len++] = extra;
3622+
3623+ zbdev->pending_id = id;
3624+ zbdev->pending_size = len;
3625+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3626+ if (!zbdev->pending_data) {
3627+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3628+ zbdev->pending_id = 0;
3629+ zbdev->pending_size = 0;
3630+ return -ENOMEM;
3631+ }
3632+ memcpy(zbdev->pending_data, buf, len);
3633+
3634+ return _send_pending_data(zbdev);
3635+}
3636+
3637+static int
3638+send_block(struct zb_device *zbdev, u8 len, u8 *data)
3639+{
3640+ u8 i = 0, buf[4]; /* 4 because of 2 start bytes, id and len */
3641+
3642+ /* Check arguments */
3643+ BUG_ON(!zbdev);
3644+
3645+ if (!zbdev->opened) {
3646+ if (!_open_dev(zbdev))
3647+ return -EAGAIN;
3648+ }
3649+
3650+ pr_debug("%s(): id = %u\n", __func__, DATA_XMIT_BLOCK);
3651+ if (zbdev->pending_size) {
3652+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3653+ __func__, zbdev->pending_id);
3654+ BUG();
3655+ }
3656+
3657+ /* Prepare a message */
3658+ buf[i++] = START_BYTE1;
3659+ buf[i++] = START_BYTE2;
3660+ buf[i++] = DATA_XMIT_BLOCK;
3661+ buf[i++] = len;
3662+
3663+ zbdev->pending_id = DATA_XMIT_BLOCK;
3664+ zbdev->pending_size = i + len;
3665+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3666+ if (!zbdev->pending_data) {
3667+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3668+ zbdev->pending_id = 0;
3669+ zbdev->pending_size = 0;
3670+ return -ENOMEM;
3671+ }
3672+ memcpy(zbdev->pending_data, buf, i);
3673+ memcpy(zbdev->pending_data + i, data, len);
3674+
3675+ return _send_pending_data(zbdev);
3676+}
3677+
3678+static void
3679+cleanup(struct zb_device *zbdev)
3680+{
3681+ zbdev->state = STATE_WAIT_START1;
3682+ zbdev->id = 0;
3683+ zbdev->param1 = 0;
3684+ zbdev->param2 = 0;
3685+ zbdev->index = 0;
3686+}
3687+
3688+static int
3689+is_command(unsigned char c)
3690+{
3691+ switch (c) {
3692+ /* ids we can get here: */
3693+ case RESP_OPEN:
3694+ case RESP_CLOSE:
3695+ case RESP_SET_CHANNEL:
3696+ case RESP_ED:
3697+ case RESP_CCA:
3698+ case RESP_SET_STATE:
3699+ case RESP_XMIT_BLOCK:
3700+ case DATA_RECV_BLOCK:
3701+ case RESP_ADDRESS:
3702+ return 1;
3703+ }
3704+ return 0;
3705+}
3706+
3707+static int
3708+_match_pending_id(struct zb_device *zbdev)
3709+{
3710+ return ((CMD_OPEN == zbdev->pending_id &&
3711+ RESP_OPEN == zbdev->id) ||
3712+ (CMD_CLOSE == zbdev->pending_id &&
3713+ RESP_CLOSE == zbdev->id) ||
3714+ (CMD_SET_CHANNEL == zbdev->pending_id &&
3715+ RESP_SET_CHANNEL == zbdev->id) ||
3716+ (CMD_ED == zbdev->pending_id &&
3717+ RESP_ED == zbdev->id) ||
3718+ (CMD_CCA == zbdev->pending_id &&
3719+ RESP_CCA == zbdev->id) ||
3720+ (CMD_SET_STATE == zbdev->pending_id &&
3721+ RESP_SET_STATE == zbdev->id) ||
3722+ (DATA_XMIT_BLOCK == zbdev->pending_id &&
3723+ RESP_XMIT_BLOCK == zbdev->id) ||
3724+ (DATA_RECV_BLOCK == zbdev->id) ||
3725+ (CMD_ADDRESS == zbdev->pending_id &&
3726+ RESP_ADDRESS == zbdev->id));
3727+}
3728+
3729+static void serial_net_rx(struct zb_device *zbdev)
3730+{
3731+ /* zbdev->param1 is LQI
3732+ * zbdev->param2 is length of data
3733+ * zbdev->data is data itself
3734+ */
3735+ struct sk_buff *skb;
3736+ skb = alloc_skb(zbdev->param2, GFP_ATOMIC);
3737+ skb_put(skb, zbdev->param2);
3738+ skb_copy_to_linear_data(skb, zbdev->data, zbdev->param2);
3739+ ieee802154_rx_irqsafe(zbdev->dev, skb, zbdev->param1);
3740+}
3741+
3742+static void
3743+process_command(struct zb_device *zbdev)
3744+{
3745+ /* Command processing */
3746+ if (!_match_pending_id(zbdev))
3747+ return;
3748+
3749+ if (RESP_OPEN == zbdev->id && STATUS_SUCCESS == zbdev->param1) {
3750+ zbdev->opened = 1;
3751+ pr_debug("Opened device\n");
3752+ complete(&zbdev->open_done);
3753+ /* Input is not processed during output, so
3754+ * using completion is not possible during output.
3755+ * so we need to handle open as any other command
3756+ * and hope for best
3757+ */
3758+ return;
3759+ }
3760+
3761+ if (!zbdev->opened)
3762+ return;
3763+
3764+ zbdev->pending_id = 0;
3765+ kfree(zbdev->pending_data);
3766+ zbdev->pending_data = NULL;
3767+ zbdev->pending_size = 0;
3768+ if (zbdev->id != DATA_RECV_BLOCK) {
3769+ /* XXX: w/around for old FW, REMOVE */
3770+ if (zbdev->param1 == STATUS_IDLE)
3771+ zbdev->status = STATUS_SUCCESS;
3772+ else
3773+ zbdev->status = zbdev->param1;
3774+ }
3775+
3776+ switch (zbdev->id) {
3777+ case RESP_ED:
3778+ zbdev->ed = zbdev->param2;
3779+ break;
3780+ case DATA_RECV_BLOCK:
3781+ pr_debug("Received block, lqi %02x, len %02x\n",
3782+ zbdev->param1, zbdev->param2);
3783+ /* zbdev->param1 is LQ, zbdev->param2 is length */
3784+ serial_net_rx(zbdev);
3785+ break;
3786+ case RESP_ADDRESS:
3787+ pr_debug("Received address, %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
3788+ zbdev->data[0], zbdev->data[1], zbdev->data[2], zbdev->data[3],
3789+ zbdev->data[4], zbdev->data[5], zbdev->data[6], zbdev->data[7]);
3790+ break;
3791+ }
3792+
3793+ wake_up(&zbdev->wq);
3794+}
3795+
3796+static void
3797+process_char(struct zb_device *zbdev, unsigned char c)
3798+{
3799+ /* Data processing */
3800+ switch (zbdev->state) {
3801+ case STATE_WAIT_START1:
3802+ if (START_BYTE1 == c)
3803+ zbdev->state = STATE_WAIT_START2;
3804+ break;
3805+
3806+ case STATE_WAIT_START2:
3807+ if (START_BYTE2 == c)
3808+ zbdev->state = STATE_WAIT_COMMAND;
3809+ else
3810+ cleanup(zbdev);
3811+ break;
3812+
3813+ case STATE_WAIT_COMMAND:
3814+ if (is_command(c)) {
3815+ zbdev->id = c;
3816+ zbdev->state = STATE_WAIT_PARAM1;
3817+ } else {
3818+ cleanup(zbdev);
3819+ printk(KERN_ERR "%s, unexpected command id: %x\n",
3820+ __func__, c);
3821+ }
3822+ break;
3823+
3824+ case STATE_WAIT_PARAM1:
3825+ zbdev->param1 = c;
3826+ if ((RESP_ED == zbdev->id) || (DATA_RECV_BLOCK == zbdev->id))
3827+ zbdev->state = STATE_WAIT_PARAM2;
3828+ else if (RESP_ADDRESS == zbdev->id) {
3829+ zbdev->param2 = 8;
3830+ zbdev->state = STATE_WAIT_DATA;
3831+ } else {
3832+ process_command(zbdev);
3833+ cleanup(zbdev);
3834+ }
3835+ break;
3836+
3837+ case STATE_WAIT_PARAM2:
3838+ zbdev->param2 = c;
3839+ if (RESP_ED == zbdev->id) {
3840+ process_command(zbdev);
3841+ cleanup(zbdev);
3842+ } else if (DATA_RECV_BLOCK == zbdev->id)
3843+ zbdev->state = STATE_WAIT_DATA;
3844+ else
3845+ cleanup(zbdev);
3846+ break;
3847+
3848+ case STATE_WAIT_DATA:
3849+ if (zbdev->index < sizeof(zbdev->data)) {
3850+ zbdev->data[zbdev->index] = c;
3851+ zbdev->index++;
3852+ /*
3853+ * Pending data is received,
3854+ * param2 is length for DATA_RECV_BLOCK
3855+ */
3856+ if (zbdev->index == zbdev->param2) {
3857+ process_command(zbdev);
3858+ cleanup(zbdev);
3859+ }
3860+ } else {
3861+ printk(KERN_ERR "%s(): data size is greater "
3862+ "than buffer available\n", __func__);
3863+ cleanup(zbdev);
3864+ }
3865+ break;
3866+
3867+ default:
3868+ cleanup(zbdev);
3869+ }
3870+}
3871+
3872+/*****************************************************************************
3873+ * Device operations for IEEE 802.15.4 PHY side interface ZigBee stack
3874+ *****************************************************************************/
3875+
3876+static int _open_dev(struct zb_device *zbdev)
3877+{
3878+ int retries;
3879+ u8 len = 0;
3880+ /* 4 because of 2 start bytes, id and optional extra */
3881+ u8 buf[4];
3882+
3883+ /* Check arguments */
3884+ BUG_ON(!zbdev);
3885+ if (zbdev->opened)
3886+ return 1;
3887+
3888+ pr_debug("%s()\n", __func__);
3889+ if (zbdev->pending_size) {
3890+ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
3891+ __func__, zbdev->pending_id);
3892+ BUG();
3893+ }
3894+
3895+ /* Prepare a message */
3896+ buf[len++] = START_BYTE1;
3897+ buf[len++] = START_BYTE2;
3898+ buf[len++] = CMD_OPEN;
3899+
3900+ zbdev->pending_id = CMD_OPEN;
3901+ zbdev->pending_size = len;
3902+ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
3903+ if (!zbdev->pending_data) {
3904+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
3905+ zbdev->pending_id = 0;
3906+ zbdev->pending_size = 0;
3907+ return -ENOMEM;
3908+ }
3909+ memcpy(zbdev->pending_data, buf, len);
3910+
3911+ retries = 5;
3912+ while (!zbdev->opened && retries) {
3913+ if (_send_pending_data(zbdev) != 0)
3914+ return 0;
3915+
3916+ /* 3 second before retransmission */
3917+ wait_for_completion_interruptible_timeout(
3918+ &zbdev->open_done, msecs_to_jiffies(1000));
3919+ --retries;
3920+ }
3921+
3922+ zbdev->pending_id = 0;
3923+ kfree(zbdev->pending_data);
3924+ zbdev->pending_data = NULL;
3925+ zbdev->pending_size = 0;
3926+
3927+ if (zbdev->opened) {
3928+ printk(KERN_INFO "Opened connection to device\n");
3929+ return 1;
3930+ }
3931+
3932+ return 0;
3933+}
3934+
3935+/* Valid channels: 1-16 */
3936+static int
3937+ieee802154_serial_set_channel(struct ieee802154_dev *dev, int page, int channel)
3938+{
3939+ struct zb_device *zbdev;
3940+ int ret = 0;
3941+
3942+ pr_debug("%s %d\n", __func__, channel);
3943+
3944+ zbdev = dev->priv;
3945+ if (NULL == zbdev) {
3946+ printk(KERN_ERR "%s: wrong phy\n", __func__);
3947+ return -EINVAL;
3948+ }
3949+
3950+ BUG_ON(page != 0);
3951+ /* Our channels are actually from 11 to 26
3952+ * We have IEEE802.15.4 channel no from 0 to 26.
3953+ * channels 0-10 are not valid for us */
3954+ BUG_ON(channel < 11 || channel > 26);
3955+ /* ... but our crappy firmware numbers channels from 1 to 16
3956+ * which is a mystery. We suould enforce that using PIB API
3957+ * but additional checking here won't kill, and gcc will
3958+ * optimize this stuff anyway. */
3959+ BUG_ON((channel - 10) < 1 && (channel - 10) > 16);
3960+ if (mutex_lock_interruptible(&zbdev->mutex))
3961+ return -EINTR;
3962+ ret = send_cmd2(zbdev, CMD_SET_CHANNEL, channel - 10);
3963+ if (ret)
3964+ goto out;
3965+
3966+ if (wait_event_interruptible_timeout(zbdev->wq,
3967+ zbdev->status != STATUS_WAIT,
3968+ msecs_to_jiffies(1000)) > 0) {
3969+ if (zbdev->status != STATUS_SUCCESS)
3970+ ret = -EBUSY;
3971+ } else
3972+ ret = -EINTR;
3973+
3974+ if (!ret)
3975+ zbdev->dev->phy->current_channel = channel;
3976+out:
3977+ mutex_unlock(&zbdev->mutex);
3978+ pr_debug("%s end\n", __func__);
3979+ return ret;
3980+}
3981+
3982+static int
3983+ieee802154_serial_ed(struct ieee802154_dev *dev, u8 *level)
3984+{
3985+ struct zb_device *zbdev;
3986+ int ret = 0;
3987+
3988+ pr_debug("%s\n", __func__);
3989+
3990+ zbdev = dev->priv;
3991+ if (NULL == zbdev) {
3992+ printk(KERN_ERR "%s: wrong phy\n", __func__);
3993+ return -EINVAL;
3994+ }
3995+
3996+ if (mutex_lock_interruptible(&zbdev->mutex))
3997+ return -EINTR;
3998+
3999+ ret = send_cmd(zbdev, CMD_ED);
4000+ if (ret)
4001+ goto out;
4002+
4003+ if (wait_event_interruptible_timeout(zbdev->wq,
4004+ zbdev->status != STATUS_WAIT,
4005+ msecs_to_jiffies(1000)) > 0) {
4006+ *level = zbdev->ed;
4007+ if (zbdev->status != STATUS_SUCCESS)
4008+ ret = -EBUSY;
4009+ } else
4010+ ret = -ETIMEDOUT;
4011+out:
4012+
4013+ mutex_unlock(&zbdev->mutex);
4014+ pr_debug("%s end\n", __func__);
4015+ return ret;
4016+}
4017+
4018+static int
4019+ieee802154_serial_address(struct ieee802154_dev *dev, u8 addr[IEEE802154_ALEN])
4020+{
4021+ struct zb_device *zbdev;
4022+ int ret = 0;
4023+
4024+ pr_debug("%s\n", __func__);
4025+
4026+ zbdev = dev->priv;
4027+ if (NULL == zbdev) {
4028+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4029+ return -EINVAL;
4030+ }
4031+
4032+ if (mutex_lock_interruptible(&zbdev->mutex))
4033+ return -EINTR;
4034+
4035+ ret = send_cmd(zbdev, CMD_ADDRESS);
4036+ if (ret)
4037+ goto out;
4038+
4039+ if (wait_event_interruptible_timeout(zbdev->wq,
4040+ zbdev->status != STATUS_WAIT,
4041+ msecs_to_jiffies(1000)) > 0) {
4042+ memcpy(addr, zbdev->data, sizeof addr);
4043+ if (zbdev->status != STATUS_SUCCESS)
4044+ ret = -EBUSY;
4045+ } else
4046+ ret = -ETIMEDOUT;
4047+out:
4048+
4049+ mutex_unlock(&zbdev->mutex);
4050+ pr_debug("%s end\n", __func__);
4051+ return ret;
4052+}
4053+
4054+static int
4055+ieee802154_serial_start(struct ieee802154_dev *dev)
4056+{
4057+ struct zb_device *zbdev;
4058+ int ret = 0;
4059+
4060+ pr_debug("%s\n", __func__);
4061+
4062+ zbdev = dev->priv;
4063+ if (NULL == zbdev) {
4064+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4065+ return -EINVAL;
4066+ }
4067+
4068+ if (mutex_lock_interruptible(&zbdev->mutex))
4069+ return -EINTR;
4070+
4071+ ret = send_cmd2(zbdev, CMD_SET_STATE, RX_MODE);
4072+ if (ret)
4073+ goto out;
4074+
4075+ if (wait_event_interruptible_timeout(zbdev->wq,
4076+ zbdev->status != STATUS_WAIT,
4077+ msecs_to_jiffies(1000)) > 0) {
4078+ if (zbdev->status != STATUS_SUCCESS)
4079+ ret = -EBUSY;
4080+ } else
4081+ ret = -ETIMEDOUT;
4082+out:
4083+ mutex_unlock(&zbdev->mutex);
4084+ pr_debug("%s end\n", __func__);
4085+ return ret;
4086+}
4087+
4088+static void
4089+ieee802154_serial_stop(struct ieee802154_dev *dev)
4090+{
4091+ struct zb_device *zbdev;
4092+ pr_debug("%s\n", __func__);
4093+
4094+ zbdev = dev->priv;
4095+ if (NULL == zbdev) {
4096+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4097+ return;
4098+ }
4099+
4100+ if (mutex_lock_interruptible(&zbdev->mutex))
4101+ return;
4102+
4103+
4104+ if (send_cmd2(zbdev, CMD_SET_STATE, FORCE_TRX_OFF) != 0)
4105+ goto out;
4106+
4107+ wait_event_interruptible_timeout(zbdev->wq,
4108+ zbdev->status != STATUS_WAIT,
4109+ msecs_to_jiffies(1000));
4110+out:
4111+ mutex_unlock(&zbdev->mutex);
4112+ pr_debug("%s end\n", __func__);
4113+}
4114+
4115+static int
4116+ieee802154_serial_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
4117+{
4118+ struct zb_device *zbdev;
4119+ int ret;
4120+
4121+ pr_debug("%s\n", __func__);
4122+
4123+ zbdev = dev->priv;
4124+ if (NULL == zbdev) {
4125+ printk(KERN_ERR "%s: wrong phy\n", __func__);
4126+ return -EINVAL;
4127+ }
4128+
4129+ if (mutex_lock_interruptible(&zbdev->mutex))
4130+ return -EINTR;
4131+
4132+ ret = send_cmd(zbdev, CMD_CCA);
4133+ if (ret)
4134+ goto out;
4135+
4136+ if (wait_event_interruptible_timeout(zbdev->wq,
4137+ zbdev->status != STATUS_WAIT,
4138+ msecs_to_jiffies(1000)) > 0) {
4139+ if (zbdev->status != STATUS_SUCCESS) {
4140+ ret = -EBUSY;
4141+ goto out;
4142+ }
4143+ } else {
4144+ ret = -ETIMEDOUT;
4145+ goto out;
4146+ }
4147+
4148+ ret = send_cmd2(zbdev, CMD_SET_STATE, TX_MODE);
4149+ if (ret)
4150+ goto out;
4151+
4152+ if (wait_event_interruptible_timeout(zbdev->wq,
4153+ zbdev->status != STATUS_WAIT,
4154+ msecs_to_jiffies(1000)) > 0) {
4155+ if (zbdev->status != STATUS_SUCCESS) {
4156+ ret = -EBUSY;
4157+ goto out;
4158+ }
4159+ } else {
4160+ ret = -ETIMEDOUT;
4161+ goto out;
4162+ }
4163+
4164+ ret = send_block(zbdev, skb->len, skb->data);
4165+ if (ret)
4166+ goto out;
4167+
4168+ if (wait_event_interruptible_timeout(zbdev->wq,
4169+ zbdev->status != STATUS_WAIT,
4170+ msecs_to_jiffies(1000)) > 0) {
4171+ if (zbdev->status != STATUS_SUCCESS) {
4172+ ret = -EBUSY;
4173+ goto out;
4174+ }
4175+ } else {
4176+ ret = -ETIMEDOUT;
4177+ goto out;
4178+ }
4179+
4180+ ret = send_cmd2(zbdev, CMD_SET_STATE, RX_MODE);
4181+ if (ret)
4182+ goto out;
4183+
4184+ if (wait_event_interruptible_timeout(zbdev->wq,
4185+ zbdev->status != STATUS_WAIT,
4186+ msecs_to_jiffies(1000)) > 0) {
4187+ if (zbdev->status != STATUS_SUCCESS) {
4188+ ret = -EBUSY;
4189+ goto out;
4190+ }
4191+ } else {
4192+ ret = -ETIMEDOUT;
4193+ goto out;
4194+ }
4195+
4196+out:
4197+
4198+ mutex_unlock(&zbdev->mutex);
4199+ pr_debug("%s end\n", __func__);
4200+ return ret;
4201+}
4202+
4203+/*****************************************************************************
4204+ * Line discipline interface for IEEE 802.15.4 serial device
4205+ *****************************************************************************/
4206+
4207+static struct ieee802154_ops serial_ops = {
4208+ .owner = THIS_MODULE,
4209+ .xmit = ieee802154_serial_xmit,
4210+ .ed = ieee802154_serial_ed,
4211+ .set_channel = ieee802154_serial_set_channel,
4212+ .start = ieee802154_serial_start,
4213+ .stop = ieee802154_serial_stop,
4214+ .ieee_addr = ieee802154_serial_address,
4215+};
4216+
4217+/*
4218+ * Called when a tty is put into ZB line discipline. Called in process context.
4219+ * Returns 0 on success.
4220+ */
4221+static int
4222+ieee802154_tty_open(struct tty_struct *tty)
4223+{
4224+ struct zb_device *zbdev = tty->disc_data;
4225+ struct ieee802154_dev *dev;
4226+ int err;
4227+
4228+ pr_debug("Openning ldisc\n");
4229+ if (!capable(CAP_NET_ADMIN))
4230+ return -EPERM;
4231+
4232+ if (tty->disc_data)
4233+ return -EBUSY;
4234+
4235+ dev = ieee802154_alloc_device(sizeof(*zbdev), &serial_ops);
4236+ if (!dev)
4237+ return -ENOMEM;
4238+
4239+ zbdev = dev->priv;
4240+ zbdev->dev = dev;
4241+
4242+ mutex_init(&zbdev->mutex);
4243+ init_completion(&zbdev->open_done);
4244+ init_waitqueue_head(&zbdev->wq);
4245+
4246+ dev->extra_tx_headroom = 0;
4247+ /* only 2.4 GHz band */
4248+ dev->phy->channels_supported[0] = 0x7fff800;
4249+
4250+ dev->flags = IEEE802154_HW_OMIT_CKSUM;
4251+
4252+ dev->parent = tty->dev;
4253+
4254+ zbdev->tty = tty_kref_get(tty);
4255+
4256+ cleanup(zbdev);
4257+
4258+ tty->disc_data = zbdev;
4259+ tty->receive_room = MAX_DATA_SIZE;
4260+
4261+ /* FIXME: why is this needed. Note don't use ldisc_ref here as the
4262+ open path is before the ldisc is referencable */
4263+
4264+ if (tty->ldisc->ops->flush_buffer)
4265+ tty->ldisc->ops->flush_buffer(tty);
4266+ tty_driver_flush_buffer(tty);
4267+
4268+ err = ieee802154_register_device(dev);
4269+ if (err) {
4270+ printk(KERN_ERR "%s: device register failed\n", __func__);
4271+ goto out_free;
4272+ }
4273+
4274+ return 0;
4275+
4276+ ieee802154_unregister_device(zbdev->dev);
4277+
4278+out_free:
4279+ tty->disc_data = NULL;
4280+ tty_kref_put(tty);
4281+ zbdev->tty = NULL;
4282+
4283+ ieee802154_free_device(zbdev->dev);
4284+
4285+ return err;
4286+}
4287+
4288+/*
4289+ * Called when the tty is put into another line discipline or it hangs up. We
4290+ * have to wait for any cpu currently executing in any of the other zb_tty_*
4291+ * routines to finish before we can call zb_tty_close and free the
4292+ * zb_serial_dev struct. This routine must be called from process context, not
4293+ * interrupt or softirq context.
4294+ */
4295+static void
4296+ieee802154_tty_close(struct tty_struct *tty)
4297+{
4298+ struct zb_device *zbdev;
4299+
4300+ zbdev = tty->disc_data;
4301+ if (NULL == zbdev) {
4302+ printk(KERN_WARNING "%s: match is not found\n", __func__);
4303+ return;
4304+ }
4305+
4306+ tty->disc_data = NULL;
4307+ tty_kref_put(tty);
4308+ zbdev->tty = NULL;
4309+
4310+ ieee802154_unregister_device(zbdev->dev);
4311+
4312+ tty_ldisc_flush(tty);
4313+ tty_driver_flush_buffer(tty);
4314+
4315+ ieee802154_free_device(zbdev->dev);
4316+}
4317+
4318+/*
4319+ * Called on tty hangup in process context.
4320+ */
4321+static int
4322+ieee802154_tty_hangup(struct tty_struct *tty)
4323+{
4324+ ieee802154_tty_close(tty);
4325+ return 0;
4326+}
4327+
4328+/*
4329+ * Called in process context only. May be re-entered
4330+ * by multiple ioctl calling threads.
4331+ */
4332+static int
4333+ieee802154_tty_ioctl(struct tty_struct *tty, struct file *file,
4334+ unsigned int cmd, unsigned long arg)
4335+{
4336+ struct zb_device *zbdev;
4337+
4338+ pr_debug("cmd = 0x%x\n", cmd);
4339+
4340+ zbdev = tty->disc_data;
4341+ if (NULL == zbdev) {
4342+ pr_debug("match is not found\n");
4343+ return -EINVAL;
4344+ }
4345+
4346+ switch (cmd) {
4347+ case TCFLSH:
4348+ return tty_perform_flush(tty, arg);
4349+ default:
4350+ /* Try the mode commands */
4351+ return tty_mode_ioctl(tty, file, cmd, arg);
4352+ }
4353+}
4354+
4355+
4356+/*
4357+ * This can now be called from hard interrupt level as well
4358+ * as soft interrupt level or mainline.
4359+ */
4360+static void
4361+ieee802154_tty_receive(struct tty_struct *tty, const unsigned char *buf,
4362+ char *cflags, int count)
4363+{
4364+ struct zb_device *zbdev;
4365+ int i;
4366+
4367+ /* Debug info */
4368+ printk(KERN_INFO "%s, received %d bytes\n", __func__,
4369+ count);
4370+#ifdef DEBUG
4371+ print_hex_dump_bytes("ieee802154_tty_receive ", DUMP_PREFIX_NONE,
4372+ buf, count);
4373+#endif
4374+
4375+ /* Actual processing */
4376+ zbdev = tty->disc_data;
4377+ if (NULL == zbdev) {
4378+ printk(KERN_ERR "%s(): record for tty is not found\n",
4379+ __func__);
4380+ return;
4381+ }
4382+ for (i = 0; i < count; ++i)
4383+ process_char(zbdev, buf[i]);
4384+#if 0
4385+ if (tty->driver->flush_chars)
4386+ tty->driver->flush_chars(tty);
4387+#endif
4388+ tty_unthrottle(tty);
4389+}
4390+
4391+/*
4392+ * Line discipline device structure
4393+ */
4394+static struct tty_ldisc_ops ieee802154_ldisc = {
4395+ .owner = THIS_MODULE,
4396+ .magic = TTY_LDISC_MAGIC,
4397+ .name = "ieee802154-ldisc",
4398+ .open = ieee802154_tty_open,
4399+ .close = ieee802154_tty_close,
4400+ .hangup = ieee802154_tty_hangup,
4401+ .receive_buf = ieee802154_tty_receive,
4402+ .ioctl = ieee802154_tty_ioctl,
4403+};
4404+
4405+/*****************************************************************************
4406+ * Module service routinues
4407+ *****************************************************************************/
4408+
4409+static int __init ieee802154_serial_init(void)
4410+{
4411+ printk(KERN_INFO "Initializing ZigBee TTY interface\n");
4412+
4413+ if (tty_register_ldisc(N_IEEE802154, &ieee802154_ldisc) != 0) {
4414+ printk(KERN_ERR "%s: line discipline register failed\n",
4415+ __func__);
4416+ return -EINVAL;
4417+ }
4418+
4419+ return 0;
4420+}
4421+
4422+static void __exit ieee802154_serial_cleanup(void)
4423+{
4424+ if (tty_unregister_ldisc(N_IEEE802154) != 0)
4425+ printk(KERN_CRIT
4426+ "failed to unregister ZigBee line discipline.\n");
4427+}
4428+
4429+module_init(ieee802154_serial_init);
4430+module_exit(ieee802154_serial_cleanup);
4431+
4432+MODULE_LICENSE("GPL");
4433+MODULE_ALIAS_LDISC(N_IEEE802154);
4434+
4435diff --git a/drivers/ieee802154/spi_atben.c b/drivers/ieee802154/spi_atben.c
4436new file mode 100644
4437index 0000000..431bfe0
4438--- /dev/null
4439@@ -0,0 +1,421 @@
4440+/*
4441+ * spi_atben.c - SPI host look-alike for ATBEN
4442+ *
4443+ * Written 2011 by Werner Almesberger
4444+ *
4445+ * This program is free software; you can redistribute it and/or modify
4446+ * it under the terms of the GNU General Public License version 2
4447+ * as published by the Free Software Foundation.
4448+ */
4449+
4450+#include <linux/kernel.h>
4451+#include <linux/module.h>
4452+#include <linux/platform_device.h>
4453+#include <linux/gpio.h>
4454+#include <linux/delay.h>
4455+#include <linux/spi/spi.h>
4456+#include <linux/spi/at86rf230.h>
4457+#include <asm/mach-jz4740/base.h>
4458+
4459+#include "at86rf230.h"
4460+
4461+
4462+enum {
4463+ VDD_OFF = 1 << 2, /* VDD disable, PD02 */
4464+ MOSI = 1 << 8, /* CMD, PD08 */
4465+ SLP_TR = 1 << 9, /* CLK, PD09 */
4466+ MISO = 1 << 10, /* DAT0, PD10 */
4467+ SCLK = 1 << 11, /* DAT1, PD11 */
4468+ IRQ = 1 << 12, /* DAT2, PD12 */
4469+ nSEL = 1 << 13, /* DAT3/CD, PD13 */
4470+};
4471+
4472+#define PDPIN (prv->regs)
4473+#define PDDATS (prv->regs+0x14)
4474+#define PDDATC (prv->regs+0x18)
4475+
4476+
4477+struct atben_prv {
4478+ struct device *dev;
4479+ void __iomem *regs;
4480+ struct resource *ioarea;
4481+ struct at86rf230_platform_data
4482+ platform_data;
4483+ /* copy platform_data so that we can adapt .reset_data */
4484+};
4485+
4486+
4487+/* ----- ATBEN reset ------------------------------------------------------- */
4488+
4489+
4490+static void atben_reset(void *reset_data)
4491+{
4492+ struct atben_prv *prv = reset_data;
4493+ const int charge = nSEL | MOSI | SLP_TR | SCLK;
4494+ const int discharge = charge | IRQ | MISO;
4495+
4496+ dev_info(prv->dev, "atben_reset\n");
4497+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 1 << 2, 1 << 2);
4498+ jz_gpio_port_direction_output(JZ_GPIO_PORTD(0), discharge);
4499+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, discharge);
4500+ msleep(100); /* let power drop */
4501+
4502+ /*
4503+ * Hack: PD12/DAT2/IRQ is an active-high interrupt input, which is
4504+ * indicated by setting its direction bit to 1. We thus must not
4505+ * configure it as an "input".
4506+ */
4507+ jz_gpio_port_direction_input(JZ_GPIO_PORTD(0), MISO);
4508+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), charge, charge);
4509+ msleep(10); /* precharge caps */
4510+
4511+ jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, VDD_OFF | SLP_TR | SCLK);
4512+ msleep(10);
4513+}
4514+
4515+
4516+/* ----- SPI transfers ----------------------------------------------------- */
4517+
4518+
4519+static void rx_only(const struct atben_prv *prv, uint8_t *buf, int len)
4520+{
4521+ uint8_t v;
4522+
4523+ while (len--) {
4524+ writel(SCLK, PDDATS);
4525+ v = readl(PDPIN) & MISO ? 0x80 : 0;
4526+ writel(SCLK, PDDATC);
4527+
4528+ #define DO_BIT(m) \
4529+ writel(SCLK, PDDATS); \
4530+ if (readl(PDPIN) & MISO) \
4531+ v |= (m); \
4532+ writel(SCLK, PDDATC)
4533+
4534+ DO_BIT(0x40);
4535+ DO_BIT(0x20);
4536+ DO_BIT(0x10);
4537+ DO_BIT(0x08);
4538+ DO_BIT(0x04);
4539+ DO_BIT(0x02);
4540+ DO_BIT(0x01);
4541+
4542+ #undef DO_BIT
4543+
4544+ *buf++ = v;
4545+ }
4546+}
4547+
4548+
4549+static void tx_only(const struct atben_prv *prv, const uint8_t *buf, int len)
4550+{
4551+ uint8_t tv;
4552+
4553+ while (len--) {
4554+ tv = *buf++;
4555+
4556+ if (tv & 0x80) {
4557+ writel(MOSI, PDDATS);
4558+ goto b6_1;
4559+ } else {
4560+ writel(MOSI, PDDATC);
4561+ goto b6_0;
4562+ }
4563+
4564+ #define DO_BIT(m, this, next) \
4565+ this##_1: \
4566+ writel(SCLK, PDDATS); \
4567+ if (tv & (m)) { \
4568+ writel(SCLK, PDDATC); \
4569+ goto next##_1; \
4570+ } else { \
4571+ writel(MOSI | SCLK, PDDATC); \
4572+ goto next##_0; \
4573+ } \
4574+ this##_0: \
4575+ writel(SCLK, PDDATS); \
4576+ writel(SCLK, PDDATC); \
4577+ if (tv & (m)) { \
4578+ writel(MOSI, PDDATS); \
4579+ goto next##_1; \
4580+ } else { \
4581+ goto next##_0; \
4582+ }
4583+
4584+ DO_BIT(0x40, b6, b5);
4585+ DO_BIT(0x20, b5, b4);
4586+ DO_BIT(0x10, b4, b3);
4587+ DO_BIT(0x08, b3, b2);
4588+ DO_BIT(0x04, b2, b1);
4589+ DO_BIT(0x02, b1, b0);
4590+ DO_BIT(0x01, b0, done);
4591+
4592+ #undef DO_BIT
4593+
4594+done_1:
4595+done_0:
4596+ writel(SCLK, PDDATS);
4597+ writel(SCLK, PDDATC);
4598+ writel(SCLK, PDDATC); /* delay to meet t5 timing */
4599+ }
4600+}
4601+
4602+
4603+static void bidir(const struct atben_prv *prv, const uint8_t *tx, uint8_t *rx,
4604+ int len)
4605+{
4606+ uint8_t mask, tv, rv;
4607+
4608+ while (len--) {
4609+ tv = *tx++;
4610+ for (mask = 0x80; mask; mask >>= 1) {
4611+ if (tv & mask)
4612+ writel(MOSI, PDDATS);
4613+ else
4614+ writel(MOSI, PDDATC);
4615+ writel(SCLK, PDDATS);
4616+ if (readl(PDPIN) & MISO)
4617+ rv |= mask;
4618+ writel(SCLK, PDDATC);
4619+ }
4620+ *rx++ = rv;
4621+ }
4622+}
4623+
4624+
4625+static int atben_transfer(struct spi_device *spi, struct spi_message *msg)
4626+{
4627+ struct atben_prv *prv = spi_master_get_devdata(spi->master);
4628+ struct spi_transfer *xfer;
4629+ const uint8_t *tx;
4630+ uint8_t *rx;
4631+
4632+ if (unlikely(list_empty(&msg->transfers))) {
4633+ dev_err(prv->dev, "transfer is empty\n");
4634+ return -EINVAL;
4635+ }
4636+
4637+ msg->actual_length = 0;
4638+
4639+ writel(nSEL, PDDATC);
4640+ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
4641+ tx = xfer->tx_buf;
4642+ rx = xfer->rx_buf;
4643+ msg->actual_length += xfer->len;
4644+
4645+ if (!tx)
4646+ rx_only(prv, rx, xfer->len);
4647+ else if (!rx)
4648+ tx_only(prv, tx, xfer->len);
4649+ else
4650+ bidir(prv, tx, rx, xfer->len);
4651+ }
4652+ writel(nSEL, PDDATS);
4653+
4654+ msg->status = 0;
4655+ msg->complete(msg->context);
4656+
4657+ return 0;
4658+}
4659+
4660+static int atben_setup(struct spi_device *spi)
4661+{
4662+ return 0;
4663+}
4664+
4665+
4666+/* ----- SPI master creation/removal --------------------------------------- */
4667+
4668+
4669+const static struct at86rf230_platform_data at86rf230_platform_data = {
4670+ .rstn = -1,
4671+ .slp_tr = JZ_GPIO_PORTD(9),
4672+ .dig2 = -1,
4673+ .reset = atben_reset,
4674+ /* set .reset_data later */
4675+};
4676+
4677+static int __devinit atben_probe(struct platform_device *pdev)
4678+{
4679+ struct spi_board_info board_info = {
4680+ .modalias = "at86rf230",
4681+ /* set .irq later */
4682+ .chip_select = 0,
4683+ .bus_num = -1,
4684+ .max_speed_hz = 8 * 1000 * 1000,
4685+ };
4686+
4687+ struct spi_master *master;
4688+ struct atben_prv *prv;
4689+ struct resource *regs;
4690+ struct spi_device *spi;
4691+ int err = -ENXIO;
4692+
4693+ master = spi_alloc_master(&pdev->dev, sizeof(*prv));
4694+ if (!master)
4695+ return -ENOMEM;
4696+
4697+ prv = spi_master_get_devdata(master);
4698+ prv->dev = &pdev->dev;
4699+ platform_set_drvdata(pdev, spi_master_get(master));
4700+
4701+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
4702+ master->bus_num = pdev->id;
4703+ master->num_chipselect = 1;
4704+ master->setup = atben_setup;
4705+ master->transfer = atben_transfer;
4706+
4707+ dev_dbg(prv->dev, "Setting up ATBEN SPI\n");
4708+
4709+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4710+ if (!regs) {
4711+ dev_err(prv->dev, "no IORESOURCE_MEM\n");
4712+ err = -ENOENT;
4713+ goto out_master;
4714+ }
4715+ prv->ioarea = request_mem_region(regs->start, resource_size(regs),
4716+ pdev->name);
4717+ if (!prv->ioarea) {
4718+ dev_err(prv->dev, "can't request ioarea\n");
4719+ goto out_master;
4720+ }
4721+
4722+ prv->regs = ioremap(regs->start, resource_size(regs));
4723+ if (!prv->regs) {
4724+ dev_err(prv->dev, "can't ioremap\n");
4725+ goto out_ioarea;
4726+ }
4727+
4728+ board_info.irq = platform_get_irq(pdev, 0);
4729+ if (board_info.irq < 0) {
4730+ dev_err(prv->dev, "can't get GPIO irq\n");
4731+ err = -ENOENT;
4732+ goto out_regs;
4733+ }
4734+
4735+ err = spi_register_master(master);
4736+ if (err) {
4737+ dev_err(prv->dev, "can't register master\n");
4738+ goto out_regs;
4739+ }
4740+
4741+ prv->platform_data = at86rf230_platform_data;
4742+ prv->platform_data.reset_data = prv;
4743+ board_info.platform_data = &prv->platform_data;
4744+
4745+ spi = spi_new_device(master, &board_info);
4746+ if (!spi) {
4747+ dev_err(&pdev->dev, "can't create new device for %s\n",
4748+ board_info.modalias);
4749+ err = -ENXIO;
4750+ goto out_registered;
4751+ }
4752+
4753+ dev_info(&spi->dev, "ATBEN ready for mischief (IRQ %d)\n",
4754+ board_info.irq);
4755+
4756+ return 0;
4757+
4758+out_registered:
4759+ spi_unregister_master(master);
4760+
4761+out_regs:
4762+ iounmap(prv->regs);
4763+
4764+out_ioarea:
4765+ release_resource(prv->ioarea);
4766+ kfree(prv->ioarea);
4767+
4768+out_master:
4769+ platform_set_drvdata(pdev, NULL);
4770+ spi_master_put(master);
4771+
4772+ return err;
4773+}
4774+
4775+static int __devexit atben_remove(struct platform_device *pdev)
4776+{
4777+ struct spi_master *master = platform_get_drvdata(pdev);
4778+ struct atben_prv *prv = spi_master_get_devdata(master);
4779+
4780+// restore GPIOs
4781+
4782+ spi_unregister_master(master);
4783+
4784+ iounmap(prv->regs);
4785+
4786+ release_resource(prv->ioarea);
4787+ kfree(prv->ioarea);
4788+
4789+ platform_set_drvdata(pdev, NULL);
4790+ spi_master_put(master);
4791+
4792+ return 0;
4793+}
4794+
4795+static struct platform_driver atben_driver = {
4796+ .driver = {
4797+ .name = "spi_atben",
4798+ .owner = THIS_MODULE,
4799+ },
4800+ .remove = __devexit_p(atben_remove),
4801+};
4802+
4803+static struct resource atben_resources[] = {
4804+ {
4805+ .start = JZ4740_GPIO_BASE_ADDR+0x300,
4806+ .end = JZ4740_GPIO_BASE_ADDR+0x3ff,
4807+ .flags = IORESOURCE_MEM,
4808+ },
4809+ {
4810+ /* set start and end later */
4811+ .flags = IORESOURCE_IRQ,
4812+ },
4813+};
4814+
4815+static struct platform_device atben_device = {
4816+ .name = "spi_atben",
4817+ .id = -1,
4818+ .num_resources = ARRAY_SIZE(atben_resources),
4819+ .resource = atben_resources,
4820+};
4821+
4822+/*
4823+ * Registering the platform device just to probe it immediately afterwards
4824+ * seems a little circuitous. Need to see if there's a better way.
4825+ *
4826+ * What we actually should do is this:
4827+ * - in module init, register the device
4828+ * - maybe probe as well, but keep the device also if the probe fails
4829+ * (due to a conflicting driver already occupying the 8:10 slot)
4830+ * - have a means for user space to kick off driver probing, e.g., when
4831+ * anything about the 8:10 slot changes
4832+ */
4833+
4834+static int __init atben_init(void)
4835+{
4836+ int err;
4837+
4838+ err = platform_device_register(&atben_device);
4839+ if (err)
4840+ return err;
4841+
4842+ atben_resources[1].start = atben_resources[1].end =
4843+ gpio_to_irq(JZ_GPIO_PORTD(12));
4844+
4845+ return platform_driver_probe(&atben_driver, atben_probe);
4846+}
4847+
4848+static void __exit atben_exit(void)
4849+{
4850+ platform_driver_unregister(&atben_driver);
4851+ platform_device_unregister(&atben_device);
4852+}
4853+
4854+module_init(atben_init);
4855+module_exit(atben_exit);
4856+
4857+
4858+MODULE_DESCRIPTION("ATBEN SPI Controller Driver");
4859+MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
4860+MODULE_LICENSE("GPL");
4861diff --git a/drivers/ieee802154/spi_atusb.c b/drivers/ieee802154/spi_atusb.c
4862new file mode 100644
4863index 0000000..44a9d03
4864--- /dev/null
4865@@ -0,0 +1,750 @@
4866+/*
4867+ * spi_atusb - SPI host look-alike for ATUSB
4868+ *
4869+ * Copyright (c) 2011 Richard Sharpe <realrichardsharpe@gmail.com>
4870+ * Copyright (c) 2011 Stefan Schmidt <stefan@datenfreihafen.org>
4871+ * Copyright (c) 2011 Werner Almesberger <werner@almesberger.net>
4872+ *
4873+ * This program is free software; you can redistribute it and/or
4874+ * modify it under the terms of the GNU General Public License as
4875+ * published by the Free Software Foundation, version 2
4876+ *
4877+ */
4878+
4879+/*
4880+ * - implement more robust interrupt synchronization
4881+ * - check URB killing in atusb_disconnect for races
4882+ * - switch from bulk to interrupt endpoint
4883+ * - implement buffer read without extra copy
4884+ * - harmonize indentation style
4885+ * - mv atusb.c ../ieee802.15.4/spi_atusb.c, or maybe atrf_atusb.c or such
4886+ * - check module load/unload
4887+ * - review dev_* severity levels
4888+ */
4889+
4890+#include <linux/kernel.h>
4891+#include <linux/module.h>
4892+#include <linux/platform_device.h>
4893+#include <linux/jiffies.h>
4894+#include <linux/timer.h>
4895+#include <linux/interrupt.h>
4896+#include <linux/usb.h>
4897+#include <linux/spi/spi.h>
4898+#include <linux/spi/at86rf230.h>
4899+
4900+#include "at86rf230.h"
4901+
4902+
4903+#define SYNC_TIMEOUT_MS 50 /* assume interrupt has been synced after
4904+ waiting this long */
4905+
4906+#define VENDOR_ID 0x20b7
4907+#define PRODUCT_ID 0x1540
4908+
4909+/* The devices we work with */
4910+static const struct usb_device_id atusb_device_table[] = {
4911+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
4912+ { },
4913+};
4914+MODULE_DEVICE_TABLE(usb, atusb_device_table);
4915+
4916+#define ATUSB_BUILD_SIZE 256
4917+struct atusb_local {
4918+ struct usb_device * udev;
4919+ /* The interface to the RF part info, if applicable */
4920+ uint8_t ep0_atusb_major;
4921+ uint8_t ep0_atusb_minor;
4922+ uint8_t atusb_hw_type;
4923+ struct spi_master *master;
4924+ int slave_irq;
4925+ struct urb *irq_urb;
4926+ uint8_t irq_buf; /* receive irq serial here*/
4927+ uint8_t irq_seen; /* last irq serial from bulk */
4928+ uint8_t irq_sync; /* last irq serial from WRITE2_SYNC */
4929+ struct tasklet_struct task; /* interrupt delivery tasklet */
4930+ struct timer_list timer; /* delay, for interrupt synch */
4931+ struct at86rf230_platform_data platform_data;
4932+ /* copy platform_data so that we can adapt .reset_data */
4933+ struct spi_device *spi;
4934+// unsigned char buffer[3];
4935+ unsigned char buffer[260]; /* XXL, just in case */
4936+ struct spi_message *msg;
4937+};
4938+
4939+/* Commands to our device. Make sure this is synced with the firmware */
4940+enum atspi_requests {
4941+ ATUSB_ID = 0x00, /* system status/control grp */
4942+ ATUSB_BUILD,
4943+ ATUSB_RESET,
4944+ ATUSB_RF_RESET = 0x10, /* debug/test group */
4945+ ATUSB_POLL_INT,
4946+ ATUSB_TEST, /* atusb-sil only */
4947+ ATUSB_TIMER,
4948+ ATUSB_GPIO,
4949+ ATUSB_SLP_TR,
4950+ ATUSB_GPIO_CLEANUP,
4951+ ATUSB_REG_WRITE = 0x20, /* transceiver group */
4952+ ATUSB_REG_READ,
4953+ ATUSB_BUF_WRITE,
4954+ ATUSB_BUF_READ,
4955+ ATUSB_SRAM_WRITE,
4956+ ATUSB_SRAM_READ,
4957+ ATUSB_SPI_WRITE = 0x30, /* SPI group */
4958+ ATUSB_SPI_READ1,
4959+ ATUSB_SPI_READ2,
4960+ ATUSB_SPI_WRITE2_SYNC,
4961+};
4962+
4963+/*
4964+ * Direction bRequest wValue wIndex wLength
4965+ *
4966+ * ->host ATUSB_ID - - 3
4967+ * ->host ATUSB_BUILD - - #bytes
4968+ * host-> ATUSB_RESET - - 0
4969+ *
4970+ * host-> ATUSB_RF_RESET - - 0
4971+ * ->host ATUSB_POLL_INT - - 1
4972+ * host-> ATUSB_TEST - - 0
4973+ * ->host ATUSB_TIMER - - #bytes (6)
4974+ * ->host ATUSB_GPIO dir+data mask+p# 3
4975+ * host-> ATUSB_SLP_TR - - 0
4976+ * host-> ATUSB_GPIO_CLEANUP - - 0
4977+ *
4978+ * host-> ATUSB_REG_WRITE value addr 0
4979+ * ->host ATUSB_REG_READ - addr 1
4980+ * host-> ATUSB_BUF_WRITE - - #bytes
4981+ * ->host ATUSB_BUF_READ - - #bytes
4982+ * host-> ATUSB_SRAM_WRITE - addr #bytes
4983+ * ->host ATUSB_SRAM_READ - addr #bytes
4984+ *
4985+ * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes
4986+ * ->host ATUSB_SPI_READ1 byte0 - #bytes
4987+ * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes
4988+ * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1
4989+ */
4990+
4991+#define ATUSB_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
4992+#define ATUSB_TO_DEV (USB_TYPE_VENDOR | USB_DIR_OUT)
4993+
4994+
4995+/* ----- Control transfers ------------------------------------------------- */
4996+
4997+
4998+static int atusb_async_errchk(struct urb *urb)
4999+{
5000+ struct atusb_local *atusb = urb->context;
5001+ struct spi_message *msg = atusb->msg;
5002+ struct usb_device *dev = atusb->udev;
5003+
5004+ if (!urb->status) {
5005+ dev_dbg(&dev->dev, "atusb_async_errchk OK len %d\n",
5006+ urb->actual_length);
5007+ return 0;
5008+ }
5009+
5010+ if (urb->status != -ENOENT && urb->status != -ECONNRESET &&
5011+ urb->status != -ESHUTDOWN)
5012+ dev_info(&dev->dev, "atusb_async_errchk FAIL error %d\n",
5013+ urb->status);
5014+
5015+ msg->actual_length = 0;
5016+
5017+ return urb->status;
5018+}
5019+
5020+static void atusb_async_finish(struct urb *urb)
5021+{
5022+ struct atusb_local *atusb = urb->context;
5023+ struct spi_message *msg = atusb->msg;
5024+
5025+ msg->status = urb->status;
5026+ msg->complete(msg->context);
5027+
5028+ kfree(urb->setup_packet);
5029+ usb_free_urb(urb);
5030+}
5031+
5032+static void atusb_ctrl_cb(struct urb *urb)
5033+{
5034+ atusb_async_errchk(urb);
5035+ atusb_async_finish(urb);
5036+}
5037+
5038+static void atusb_timer(unsigned long data)
5039+{
5040+ struct urb *urb = (void *) data;
5041+
5042+ dev_warn(&urb->dev->dev, "atusb_timer\n");
5043+ atusb_async_finish(urb);
5044+}
5045+
5046+static void atusb_ctrl_cb_sync(struct urb *urb)
5047+{
5048+ struct atusb_local *atusb = urb->context;
5049+
5050+ /* @@@ needs locking/atomic */
5051+ if (atusb_async_errchk(urb) || atusb->irq_sync == atusb->irq_seen) {
5052+ atusb_async_finish(urb);
5053+ return;
5054+ }
5055+
5056+ BUG_ON(timer_pending(&atusb->timer));
5057+ atusb->timer.expires = jiffies+msecs_to_jiffies(SYNC_TIMEOUT_MS);
5058+ atusb->timer.data = (unsigned long) urb;
5059+ add_timer(&atusb->timer);
5060+}
5061+
5062+static void atusb_read_fb_cb(struct urb *urb)
5063+{
5064+ struct atusb_local *atusb = urb->context;
5065+ struct spi_message *msg = atusb->msg;
5066+ const struct spi_transfer *xfer;
5067+ uint8_t *rx;
5068+
5069+ if (!atusb_async_errchk(urb)) {
5070+ BUG_ON(!urb->actual_length);
5071+
5072+ xfer = list_first_entry(&msg->transfers, struct spi_transfer,
5073+ transfer_list);
5074+ rx = xfer->rx_buf;
5075+ rx[1] = atusb->buffer[0];
5076+
5077+ xfer = list_entry(xfer->transfer_list.next,
5078+ struct spi_transfer, transfer_list);
5079+ memcpy(xfer->rx_buf, atusb->buffer+1, urb->actual_length-1);
5080+ }
5081+
5082+ atusb_async_finish(urb);
5083+}
5084+
5085+static int submit_control_msg(struct atusb_local *atusb,
5086+ __u8 request, __u8 requesttype, __u16 value, __u16 index,
5087+ void *data, __u16 size, usb_complete_t complete_fn, void *context)
5088+{
5089+ struct usb_device *dev = atusb->udev;
5090+ struct usb_ctrlrequest *req;
5091+ struct urb *urb;
5092+ int retval = -ENOMEM;
5093+
5094+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
5095+ if (!req)
5096+ return -ENOMEM;
5097+
5098+ req->bRequest = request;
5099+ req->bRequestType = requesttype;
5100+ req->wValue = cpu_to_le16(value);
5101+ req->wIndex = cpu_to_le16(index);
5102+ req->wLength = cpu_to_le16(size);
5103+
5104+ urb = usb_alloc_urb(0, GFP_KERNEL);
5105+ if (!urb)
5106+ goto out_nourb;
5107+
5108+ usb_fill_control_urb(urb, dev,
5109+ requesttype == ATUSB_FROM_DEV ?
5110+ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0),
5111+ (unsigned char *) req, data, size, complete_fn, context);
5112+
5113+ retval = usb_submit_urb(urb, GFP_KERNEL);
5114+ if (!retval)
5115+ return 0;
5116+ dev_warn(&dev->dev, "failed submitting read urb, error %d",
5117+ retval);
5118+ retval = retval == -ENOMEM ? retval : -EIO;
5119+
5120+ usb_free_urb(urb);
5121+out_nourb:
5122+ kfree(req);
5123+
5124+ return retval;
5125+}
5126+
5127+
5128+/* ----- SPI transfers ----------------------------------------------------- */
5129+
5130+
5131+static int atusb_read1(struct atusb_local *atusb,
5132+ uint8_t tx, uint8_t *rx, int len)
5133+{
5134+ dev_dbg(&atusb->udev->dev, "atusb_read1: tx = 0x%x\n", tx);
5135+ return submit_control_msg(atusb,
5136+ ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
5137+ rx, 1, atusb_ctrl_cb, atusb);
5138+}
5139+
5140+static int atusb_read_fb(struct atusb_local *atusb,
5141+ uint8_t tx, uint8_t *rx0, uint8_t *rx, int len)
5142+{
5143+ dev_dbg(&atusb->udev->dev, "atusb_read_fb: tx = 0x%x\n", tx);
5144+ return submit_control_msg(atusb,
5145+ ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
5146+ atusb->buffer, len+1, atusb_read_fb_cb, atusb);
5147+}
5148+
5149+static int atusb_write(struct atusb_local *atusb,
5150+ uint8_t tx0, uint8_t tx1, const uint8_t *tx, int len)
5151+{
5152+ dev_dbg(&atusb->udev->dev,
5153+ "atusb_write: tx0 = 0x%x tx1 = 0x%x\n", tx0, tx1);
5154+
5155+ /*
5156+ * The AT86RF230 driver sometimes requires a transceiver state
5157+ * transition to be an interrupt barrier. This is the case after
5158+ * writing FORCE_TX_ON to the TRX_CMD field in the TRX_STATE register.
5159+ *
5160+ * Since there is no other means of notification, we just decode the
5161+ * transfer and do a bit of pattern matching.
5162+ */
5163+ if (tx0 == (CMD_REG | CMD_WRITE | RG_TRX_STATE) &&
5164+ (tx1 & 0x1f) == STATE_FORCE_TX_ON)
5165+ return submit_control_msg(atusb,
5166+ ATUSB_SPI_WRITE2_SYNC, ATUSB_FROM_DEV, tx0, tx1,
5167+ &atusb->irq_sync, 1, atusb_ctrl_cb_sync, atusb);
5168+ else
5169+ return submit_control_msg(atusb,
5170+ ATUSB_SPI_WRITE, ATUSB_TO_DEV, tx0, tx1,
5171+ (uint8_t *) tx, len, atusb_ctrl_cb, atusb);
5172+}
5173+
5174+static int atusb_transfer(struct spi_device *spi, struct spi_message *msg)
5175+{
5176+ struct atusb_local *atusb = spi_master_get_devdata(spi->master);
5177+ struct spi_transfer *xfer;
5178+ struct spi_transfer *x[2];
5179+ int n;
5180+ const uint8_t *tx;
5181+ uint8_t *rx;
5182+ int len;
5183+ int retval = 0;
5184+
5185+ if (unlikely(list_empty(&msg->transfers))) {
5186+ dev_err(&atusb->udev->dev, "transfer is empty\n");
5187+ return -EINVAL;
5188+ }
5189+
5190+ atusb->msg = msg;
5191+
5192+ /* Classify the request */
5193+ n = 0;
5194+ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
5195+ if (n == ARRAY_SIZE(x)) {
5196+ dev_err(&atusb->udev->dev, "too many transfers\n");
5197+ return -EINVAL;
5198+ }
5199+ x[n] = xfer;
5200+ n++;
5201+ }
5202+
5203+ tx = x[0]->tx_buf;
5204+ rx = x[0]->rx_buf;
5205+ len = x[0]->len;
5206+
5207+ msg->actual_length = len;
5208+
5209+ if (!tx || len != 2)
5210+ goto bad_req;
5211+ if (n == 1) {
5212+ if (rx) {
5213+ dev_dbg(&atusb->udev->dev, "read 1\n");
5214+ retval = atusb_read1(atusb, tx[0], rx+1, len-1);
5215+ } else {
5216+ dev_dbg(&atusb->udev->dev, "write 2\n");
5217+ /*
5218+ * Don't take our clock away !! ;-)
5219+ */
5220+ if (tx[0] == (CMD_REG | CMD_WRITE | RG_TRX_CTRL_0)) {
5221+ msg->status = 0;
5222+ msg->complete(msg->context);
5223+ } else {
5224+ retval = atusb_write(atusb,
5225+ tx[0], tx[1], NULL, 0);
5226+ }
5227+ }
5228+ } else {
5229+ if (x[0]->rx_buf) {
5230+ if (x[1]->tx_buf || !x[1]->rx_buf)
5231+ goto bad_req;
5232+ dev_dbg(&atusb->udev->dev, "read 1+\n");
5233+ retval = atusb_read_fb(atusb, tx[0], rx+1,
5234+ x[1]->rx_buf, x[1]->len);
5235+ } else {
5236+ if (!x[1]->tx_buf ||x[1]->rx_buf)
5237+ goto bad_req;
5238+ dev_dbg(&atusb->udev->dev, "write 2+n\n");
5239+ retval = atusb_write(atusb, tx[0], tx[1],
5240+ x[1]->tx_buf, x[1]->len);
5241+ }
5242+ }
5243+ return retval;
5244+
5245+bad_req:
5246+ dev_err(&atusb->udev->dev, "unrecognized request:\n");
5247+ list_for_each_entry(xfer, &msg->transfers, transfer_list)
5248+ dev_err(&atusb->udev->dev, "%stx %srx len %u\n",
5249+ xfer->tx_buf ? "" : "!", xfer->rx_buf ? " " : "!",
5250+ xfer->len);
5251+ return -EINVAL;
5252+}
5253+
5254+static int atusb_setup(struct spi_device *spi)
5255+{
5256+ return 0;
5257+}
5258+
5259+
5260+/* ----- Interrupt handling ------------------------------------------------ */
5261+
5262+
5263+static void atusb_tasklet(unsigned long data)
5264+{
5265+ struct atusb_local *atusb = (void *) data;
5266+
5267+ generic_handle_irq(atusb->slave_irq);
5268+}
5269+
5270+static void atusb_irq(struct urb *urb)
5271+{
5272+ struct atusb_local *atusb = urb->context;
5273+
5274+ dev_dbg(&urb->dev->dev, "atusb_irq (%d), seen %d sync %d\n",
5275+ urb->status, atusb->irq_buf, atusb->irq_sync);
5276+ if (!urb->status) {
5277+ atusb->irq_seen = atusb->irq_buf;
5278+ if (atusb->irq_sync == atusb->irq_seen &&
5279+ try_to_del_timer_sync(&atusb->timer) == 1)
5280+ atusb_async_finish((struct urb *) atusb->timer.data);
5281+ }
5282+ usb_free_urb(urb);
5283+ atusb->irq_urb = NULL;
5284+ tasklet_schedule(&atusb->task);
5285+}
5286+
5287+static int atusb_arm_interrupt(struct atusb_local *atusb)
5288+{
5289+ struct usb_device *dev = atusb->udev;
5290+ struct urb *urb;
5291+ int retval = -ENOMEM;
5292+
5293+ BUG_ON(atusb->irq_urb);
5294+
5295+ dev_vdbg(&dev->dev, "atusb_arm_interrupt\n");
5296+ urb = usb_alloc_urb(0, GFP_KERNEL);
5297+ if (!urb) {
5298+ dev_err(&dev->dev,
5299+ "atusb_arm_interrupt: usb_alloc_urb failed\n");
5300+ return -ENOMEM;
5301+ }
5302+
5303+ usb_fill_bulk_urb(urb, dev, usb_rcvbulkpipe(dev, 1),
5304+ &atusb->irq_buf, 1, atusb_irq, atusb);
5305+ atusb->irq_urb = urb;
5306+ retval = usb_submit_urb(urb, GFP_KERNEL);
5307+ if (!retval)
5308+ return 0;
5309+
5310+ dev_err(&dev->dev, "failed submitting bulk urb, error %d\n", retval);
5311+ retval = retval == -ENOMEM ? retval : -EIO;
5312+
5313+ usb_free_urb(urb);
5314+
5315+ return retval;
5316+}
5317+
5318+static void atusb_irq_mask(struct irq_data *data)
5319+{
5320+ struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
5321+
5322+ dev_vdbg(&atusb->udev->dev, "atusb_irq_mask\n");
5323+ tasklet_disable_nosync(&atusb->task);
5324+}
5325+
5326+static void atusb_irq_unmask(struct irq_data *data)
5327+{
5328+ struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
5329+
5330+ dev_vdbg(&atusb->udev->dev, "atusb_irq_unmask\n");
5331+ tasklet_enable(&atusb->task);
5332+}
5333+
5334+static void atusb_irq_ack(struct irq_data *data)
5335+{
5336+ struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
5337+
5338+ dev_vdbg(&atusb->udev->dev, "atusb_irq_ack\n");
5339+ atusb_arm_interrupt(atusb);
5340+}
5341+
5342+static struct irq_chip atusb_irq_chip = {
5343+ .name = "atusb-slave",
5344+ .irq_mask = atusb_irq_mask,
5345+ .irq_unmask = atusb_irq_unmask,
5346+ .irq_ack = atusb_irq_ack,
5347+};
5348+
5349+
5350+/* ----- Transceiver reset ------------------------------------------------- */
5351+
5352+
5353+static void atusb_reset(void *reset_data)
5354+{
5355+ int retval;
5356+ struct atusb_local *atusb = reset_data;
5357+
5358+ retval = usb_control_msg(atusb->udev,
5359+ usb_rcvctrlpipe(atusb->udev, 0),
5360+ ATUSB_RF_RESET, ATUSB_TO_DEV, 0, 0,
5361+ NULL, 0, 1000);
5362+ if (retval < 0) {
5363+ dev_err(&atusb->udev->dev,
5364+ "%s: error doing reset retval = %d\n",
5365+ __func__, retval);
5366+ }
5367+}
5368+
5369+
5370+/* ----- Firmware version information -------------------------------------- */
5371+
5372+
5373+static int atusb_get_and_show_revision(struct atusb_local *atusb)
5374+{
5375+ struct usb_device *dev = atusb->udev;
5376+ int retval;
5377+
5378+ /* Get a couple of the ATMega Firmware values */
5379+ retval = usb_control_msg(dev,
5380+ usb_rcvctrlpipe(dev, 0),
5381+ ATUSB_ID, ATUSB_FROM_DEV, 0, 0,
5382+ atusb->buffer, 3, 1000);
5383+ if (retval < 0) {
5384+ dev_info(&dev->dev,
5385+ "failed submitting urb for ATUSB_ID, error %d\n", retval);
5386+ return retval == -ENOMEM ? retval : -EIO;
5387+ }
5388+
5389+ atusb->ep0_atusb_major = atusb->buffer[0];
5390+ atusb->ep0_atusb_minor = atusb->buffer[1];
5391+ atusb->atusb_hw_type = atusb->buffer[2];
5392+ dev_info(&dev->dev,
5393+ "Firmware: major: %u, minor: %u, hardware type: %u\n",
5394+ atusb->ep0_atusb_major, atusb->ep0_atusb_minor,
5395+ atusb->atusb_hw_type);
5396+
5397+ return 0;
5398+}
5399+
5400+static int atusb_get_and_show_build(struct atusb_local *atusb)
5401+{
5402+ struct usb_device *dev = atusb->udev;
5403+ char build[ATUSB_BUILD_SIZE+1];
5404+ int retval;
5405+
5406+ retval = usb_control_msg(dev,
5407+ usb_rcvctrlpipe(atusb->udev, 0),
5408+ ATUSB_BUILD, ATUSB_FROM_DEV, 0, 0,
5409+ build, ATUSB_BUILD_SIZE, 1000);
5410+ if (retval < 0) {
5411+ dev_err(&dev->dev,
5412+ "failed submitting urb for ATUSB_BUILD, error %d\n",
5413+ retval);
5414+ return retval == -ENOMEM ? retval : -EIO;
5415+ }
5416+
5417+ build[retval] = 0;
5418+ dev_info(&dev->dev, "Firmware: build %s\n", build);
5419+
5420+ return 0;
5421+}
5422+
5423+
5424+/* ----- Setup ------------------------------------------------------------- */
5425+
5426+
5427+struct at86rf230_platform_data at86rf230_platform_data = {
5428+ .rstn = -1,
5429+ .slp_tr = -1,
5430+ .dig2 = -1,
5431+ .reset = atusb_reset,
5432+ /* set .reset_data later */
5433+};
5434+
5435+static int atusb_probe(struct usb_interface *interface,
5436+ const struct usb_device_id *id)
5437+{
5438+ struct spi_board_info board_info = {
5439+ .modalias = "at86rf230",
5440+ /* set .irq later */
5441+ .chip_select = 0,
5442+ .bus_num = -1,
5443+ .max_speed_hz = 8 * 1000 * 1000,
5444+ };
5445+
5446+ struct usb_device *udev = interface_to_usbdev(interface);
5447+ struct atusb_local *atusb = NULL;
5448+ struct spi_master *master;
5449+ int retval;
5450+
5451+ /*
5452+ * Ignore all interfaces used for DFU, i.e., everything while in the
5453+ * boot loader, and interface #1 when in the application.
5454+ */
5455+ if (interface->cur_altsetting->desc.bInterfaceClass !=
5456+ USB_CLASS_VENDOR_SPEC) {
5457+ dev_dbg(&udev->dev,
5458+ "Ignoring interface with class 0x%02x\n",
5459+ interface->cur_altsetting->desc.bInterfaceClass);
5460+ return -ENODEV;
5461+ }
5462+
5463+ master = spi_alloc_master(&udev->dev, sizeof(*atusb));
5464+ if (!master)
5465+ return -ENOMEM;
5466+
5467+ atusb = spi_master_get_devdata(master);
5468+
5469+ atusb->udev = usb_get_dev(udev);
5470+ usb_set_intfdata(interface, atusb);
5471+
5472+ atusb->master = spi_master_get(master);
5473+
5474+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
5475+ master->bus_num = -1;
5476+ master->num_chipselect = 1;
5477+ master->setup = atusb_setup;
5478+ master->transfer = atusb_transfer;
5479+
5480+ atusb->slave_irq = irq_alloc_desc(numa_node_id());
5481+ if (atusb->slave_irq < 0) {
5482+ dev_err(&udev->dev, "can't allocate slave irq\n");
5483+ retval = -ENXIO;
5484+ goto err_free;
5485+ }
5486+
5487+ irq_set_chip_data(atusb->slave_irq, atusb);
5488+ irq_set_chip_and_handler(atusb->slave_irq, &atusb_irq_chip,
5489+ handle_level_irq);
5490+
5491+ /* FIXME prepare USB IRQ */
5492+
5493+ retval = spi_register_master(master);
5494+ if (retval < 0) {
5495+ dev_err(&udev->dev, "can't register spi master\n");
5496+ goto err_slave_irq;
5497+ }
5498+
5499+ atusb->platform_data = at86rf230_platform_data;
5500+ atusb->platform_data.reset_data = atusb;
5501+ board_info.platform_data = &atusb->platform_data;
5502+ board_info.irq = atusb->slave_irq;
5503+
5504+ init_timer(&atusb->timer);
5505+ atusb->timer.function = atusb_timer;
5506+
5507+ tasklet_init(&atusb->task, atusb_tasklet, (unsigned long) atusb);
5508+ tasklet_disable(&atusb->task);
5509+ atusb_arm_interrupt(atusb);
5510+
5511+ if (atusb_get_and_show_revision(atusb) < 0)
5512+ goto err_master;
5513+ if (atusb_get_and_show_build(atusb) < 0)
5514+ goto err_master;
5515+
5516+ atusb->spi = spi_new_device(master, &board_info);
5517+ if (!atusb->spi) {
5518+ dev_err(&udev->dev, "can't create new device for %s\n",
5519+ board_info.modalias);
5520+ goto err_master;
5521+ }
5522+
5523+ dev_info(&atusb->spi->dev,
5524+ "ATUSB ready for mischief (IRQ %d)\n", board_info.irq);
5525+
5526+ return 0;
5527+
5528+err_master:
5529+ /*
5530+ * If we come here from a partially successful driver initialization,
5531+ * we don't really know how much it has done. In particular, it may
5532+ * have triggered an interrupt and thus removed the interrupt URB and
5533+ * maybe scheduled the tasklet.
5534+ */
5535+ tasklet_disable(&atusb->task);
5536+ if (atusb->irq_urb)
5537+ usb_kill_urb(atusb->irq_urb);
5538+ spi_master_put(atusb->master);
5539+err_slave_irq:
5540+ irq_set_chained_handler(atusb->slave_irq, NULL);
5541+ irq_set_chip_data(atusb->slave_irq, NULL);
5542+ irq_free_desc(atusb->slave_irq);
5543+err_free:
5544+ return retval;
5545+}
5546+
5547+static void atusb_disconnect(struct usb_interface *interface)
5548+{
5549+ struct atusb_local *atusb = usb_get_intfdata(interface);
5550+ struct spi_master *master = atusb->master;
5551+
5552+ tasklet_disable(&atusb->task);
5553+ /* @@@ this needs some extra protecion - wa */
5554+ if (atusb->irq_urb)
5555+ usb_kill_urb(atusb->irq_urb);
5556+
5557+ BUG_ON(timer_pending(&atusb->timer));
5558+
5559+ usb_set_intfdata(interface, NULL);
5560+ usb_put_dev(atusb->udev);
5561+
5562+ spi_dev_put(atusb->spi);
5563+
5564+ spi_unregister_master(master);
5565+
5566+ irq_set_chained_handler(atusb->slave_irq, NULL);
5567+ irq_set_chip_data(atusb->slave_irq, NULL);
5568+ irq_free_desc(atusb->slave_irq);
5569+
5570+ spi_master_put(master);
5571+}
5572+
5573+void atusb_release(struct device *dev)
5574+{
5575+ return;
5576+}
5577+
5578+static struct usb_driver atusb_driver = {
5579+ .name = "atusb_ben-wpan",
5580+ .probe = atusb_probe,
5581+ .disconnect = atusb_disconnect,
5582+ .id_table = atusb_device_table,
5583+};
5584+
5585+static struct platform_device atusb_device = {
5586+ .name = "spi_atusb",
5587+ .id = -1,
5588+ .dev.release = atusb_release,
5589+};
5590+
5591+static int __init atusb_init(void)
5592+{
5593+ int retval;
5594+
5595+ retval = platform_device_register(&atusb_device);
5596+ if (retval)
5597+ return retval;
5598+
5599+ return usb_register(&atusb_driver);
5600+}
5601+
5602+static void __exit atusb_exit(void)
5603+{
5604+ usb_deregister(&atusb_driver);
5605+ platform_device_unregister(&atusb_device);
5606+}
5607+
5608+module_init (atusb_init);
5609+module_exit (atusb_exit);
5610+
5611+MODULE_AUTHOR("Richard Sharpe <realrichardsharpe@gmail.com>");
5612+MODULE_AUTHOR("Stefan Schmidt <stefan@datenfreihafen.org>");
5613+MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
5614+MODULE_DESCRIPTION("ATUSB ben-wpan Driver");
5615+MODULE_LICENSE("GPL");
5616diff --git a/include/linux/if_ieee802154.h b/include/linux/if_ieee802154.h
5617new file mode 100644
5618index 0000000..cce32bb
5619--- /dev/null
5620@@ -0,0 +1,6 @@
5621+#ifndef __LINUX_IF_IEEE802154_H
5622+#define __LINUX_IF_IEEE802154_H
5623+
5624+#define IEEE802154_ALEN 8 /* size of 64-bit hardware address */
5625+
5626+#endif
5627diff --git a/include/linux/spi/at86rf230.h b/include/linux/spi/at86rf230.h
5628new file mode 100644
5629index 0000000..dff0225
5630--- /dev/null
5631@@ -0,0 +1,34 @@
5632+/*
5633+ * AT86RF230/RF231 driver
5634+ *
5635+ * Copyright (C) 2009 Siemens AG
5636+ *
5637+ * This program is free software; you can redistribute it and/or modify
5638+ * it under the terms of the GNU General Public License version 2
5639+ * as published by the Free Software Foundation.
5640+ *
5641+ * This program is distributed in the hope that it will be useful,
5642+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5643+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5644+ * GNU General Public License for more details.
5645+ *
5646+ * You should have received a copy of the GNU General Public License along
5647+ * with this program; if not, write to the Free Software Foundation, Inc.,
5648+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5649+ *
5650+ * Written by:
5651+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
5652+ */
5653+#ifndef LINUX_SPI_AT86RF230_H
5654+#define LINUX_SPI_AT86RF230_H
5655+
5656+struct at86rf230_platform_data {
5657+ int rstn;
5658+ int slp_tr;
5659+ int dig2;
5660+ void (*reset)(void *reset_data);
5661+ void *reset_data;
5662+};
5663+
5664+#endif
5665+
5666diff --git a/include/net/mac802154.h b/include/net/mac802154.h
5667new file mode 100644
5668index 0000000..df46f6a
5669--- /dev/null
5670@@ -0,0 +1,156 @@
5671+/*
5672+ * IEEE802.15.4-2003 specification
5673+ *
5674+ * Copyright (C) 2007, 2008 Siemens AG
5675+ *
5676+ * This program is free software; you can redistribute it and/or modify
5677+ * it under the terms of the GNU General Public License version 2
5678+ * as published by the Free Software Foundation.
5679+ *
5680+ * This program is distributed in the hope that it will be useful,
5681+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5682+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5683+ * GNU General Public License for more details.
5684+ *
5685+ * You should have received a copy of the GNU General Public License along
5686+ * with this program; if not, write to the Free Software Foundation, Inc.,
5687+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5688+ *
5689+ * Written by:
5690+ */
5691+#ifndef NET_MAC802154_H
5692+#define NET_MAC802154_H
5693+
5694+#include <linux/if_ieee802154.h>
5695+
5696+/**
5697+ * enum ieee802154_hw_addr_filt_flags - hardware flags
5698+ *
5699+ * These flags are used to indicate changed address settings from
5700+ * the stack to the hardware.
5701+ *
5702+ * @IEEE802515_SADDR_CHANGED:
5703+ * Indicates that the Short Address changed
5704+ *
5705+ * @IEEE802515_IEEEADDR_CHANGED:
5706+ * Indicates that the IEEE Address changed
5707+ *
5708+ * @IEEE802515_PANID_CHANGED:
5709+ * Indicates that the PAN ID changed
5710+ *
5711+ * @IEEE802515_PANC_CHANGED:
5712+ * Indicates that PAN Coordinator status changed
5713+ */
5714+enum ieee802154_hw_addr_filt_flags {
5715+ IEEE802515_SADDR_CHANGED = 1 << 0,
5716+ IEEE802515_IEEEADDR_CHANGED = 1 << 1,
5717+ IEEE802515_PANID_CHANGED = 1 << 2,
5718+ IEEE802515_PANC_CHANGED = 1 << 3,
5719+};
5720+
5721+struct ieee802154_hw_addr_filt {
5722+ u16 pan_id;
5723+ u16 short_addr;
5724+ u8 ieee_addr[IEEE802154_ALEN];
5725+ u8 pan_coord;
5726+};
5727+
5728+struct ieee802154_dev {
5729+ /* filled by the driver */
5730+ int extra_tx_headroom; /* headroom to reserve for tx skb */
5731+ u32 flags; /* Flags for device to set */
5732+ struct device *parent;
5733+
5734+ /* filled by mac802154 core */
5735+ struct ieee802154_hw_addr_filt hw_filt;
5736+ void *priv; /* driver-specific data */
5737+ struct wpan_phy *phy;
5738+};
5739+
5740+/* Checksum is in hardware and is omitted from packet */
5741+/**
5742+ * enum ieee802154_hw_flags - hardware flags
5743+ *
5744+ * These flags are used to indicate hardware capabilities to
5745+ * the stack. Generally, flags here should have their meaning
5746+ * done in a way that the simplest hardware doesn't need setting
5747+ * any particular flags. There are some exceptions to this rule,
5748+ * however, so you are advised to review these flags carefully.
5749+ *
5750+ * @IEEE802154_HW_OMIT_CKSUM:
5751+ * Indicates that receiver omits FCS and transmitter will add
5752+ * FCS on it's own.
5753+ *
5754+ * @IEEE802154_HW_AACK:
5755+ * Indicates that receiver will autorespond with ACK frames.
5756+ */
5757+enum ieee802154_hw_flags {
5758+ IEEE802154_HW_OMIT_CKSUM = 1 << 0,
5759+ IEEE802154_HW_AACK = 1 << 1,
5760+};
5761+
5762+struct sk_buff;
5763+
5764+/**
5765+ * struct ieee802154_ops - callbacks from mac802154 to the driver
5766+ *
5767+ * This structure contains various callbacks that the driver may
5768+ * handle or, in some cases, must handle, for example to transmit
5769+ * a frame.
5770+ *
5771+ * @start: Handler that 802.15.4 module calls for device initialisation.
5772+ * This function is called before the first interface is attached.
5773+ *
5774+ * @stop: Handler that 802.15.4 module calls for device cleanup
5775+ * This function is called after the last interface is removed.
5776+ *
5777+ * @xmit: Handler that 802.15.4 module calls for each transmitted frame.
5778+ * skb cntains the buffer starting from the IEEE 802.15.4 header.
5779+ * The low-level driver should send the frame based on available
5780+ * configuration.
5781+ * This function should return zero or negative errno.
5782+ * Called with pib_lock held.
5783+ *
5784+ * @ed: Handler that 802.15.4 module calls for Energy Detection.
5785+ * This function should place the value for detected energy
5786+ * (usually device-dependant) in the level pointer and return
5787+ * either zero or negative errno.
5788+ * Called with pib_lock held.
5789+ *
5790+ * @set_channel: Set radio for listening on specific channel.
5791+ * Set the device for listening on specified channel.
5792+ * Returns either zero, or negative errno.
5793+ * Called with pib_lock held.
5794+ *
5795+ * @set_hw_addr_filt: Set radio for listening on specific address.
5796+ * Set the device for listening on specified address.
5797+ * Returns either zero, or negative errno.
5798+ */
5799+struct ieee802154_ops {
5800+ struct module *owner;
5801+ int (*start)(struct ieee802154_dev *dev);
5802+ void (*stop)(struct ieee802154_dev *dev);
5803+ int (*xmit)(struct ieee802154_dev *dev,
5804+ struct sk_buff *skb);
5805+ int (*ed)(struct ieee802154_dev *dev, u8 *level);
5806+ int (*set_channel)(struct ieee802154_dev *dev,
5807+ int page,
5808+ int channel);
5809+ int (*set_hw_addr_filt)(struct ieee802154_dev *dev,
5810+ struct ieee802154_hw_addr_filt *filt,
5811+ unsigned long changed);
5812+ int (*ieee_addr)(struct ieee802154_dev *dev,
5813+ u8 addr[IEEE802154_ALEN]);
5814+};
5815+
5816+struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
5817+ struct ieee802154_ops *ops);
5818+int ieee802154_register_device(struct ieee802154_dev *dev);
5819+void ieee802154_unregister_device(struct ieee802154_dev *dev);
5820+void ieee802154_free_device(struct ieee802154_dev *dev);
5821+
5822+void ieee802154_rx(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi);
5823+void ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb,
5824+ u8 lqi);
5825+#endif
5826+
5827diff --git a/net/mac802154/Kconfig b/net/mac802154/Kconfig
5828new file mode 100644
5829index 0000000..32e63bc
5830--- /dev/null
5831@@ -0,0 +1,24 @@
5832+config MAC802154
5833+ tristate "Generic IEEE 802.15.4 Soft Networking Stack (mac802154)"
5834+ depends on IEEE802154 && EXPERIMENTAL
5835+ select CRC_CCITT
5836+ ---help---
5837+ This option enables the hardware independent IEEE 802.15.4
5838+ networking stack for SoftMAC devices (the ones implementing
5839+ only PHY level of IEEE 802.15.4 standard).
5840+
5841+ Note: this implementation is neither certified, nor feature
5842+ complete! We do not guarantee that it is compatible w/ other
5843+ implementations, etc.
5844+
5845+ If you plan to use HardMAC IEEE 802.15.4 devices, you can
5846+ say N here. Alternatievly you can say M to compile it as
5847+ module.
5848+
5849+config MAC802154_DEBUG
5850+ bool "IEEE 802.15.4 SoftMAC debugging messages"
5851+ depends on MAC802154
5852+ default y
5853+ help
5854+ Say Y here to make the IEEE 802.15.4 SoftMAC generate extensive
5855+ debugging messages.
5856diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
5857new file mode 100644
5858index 0000000..d76fabb
5859--- /dev/null
5860@@ -0,0 +1,6 @@
5861+obj-$(CONFIG_MAC802154) += mac802154.o
5862+mac802154-objs := rx.o tx.o main.o monitor.o wpan.o mac_cmd.o scan.o mib.o \
5863+ beacon.o beacon_hash.o smac.o
5864+
5865+ccflags-$(CONFIG_MAC802154_DEBUG) += -DDEBUG
5866+ccflags-y += -Wall
5867diff --git a/net/mac802154/beacon.c b/net/mac802154/beacon.c
5868new file mode 100644
5869index 0000000..fbf67e9
5870--- /dev/null
5871@@ -0,0 +1,285 @@
5872+/*
5873+ * MAC beacon interface
5874+ *
5875+ * Copyright 2007, 2008 Siemens AG
5876+ *
5877+ * This program is free software; you can redistribute it and/or modify
5878+ * it under the terms of the GNU General Public License version 2
5879+ * as published by the Free Software Foundation.
5880+ *
5881+ * This program is distributed in the hope that it will be useful,
5882+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5883+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5884+ * GNU General Public License for more details.
5885+ *
5886+ * You should have received a copy of the GNU General Public License along
5887+ * with this program; if not, write to the Free Software Foundation, Inc.,
5888+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5889+ *
5890+ * Written by:
5891+ * Sergey Lapin <slapin@ossfans.org>
5892+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
5893+ */
5894+
5895+#include <linux/kernel.h>
5896+#include <linux/slab.h>
5897+#include <linux/if_arp.h>
5898+#include <linux/list.h>
5899+
5900+#include <net/af_ieee802154.h>
5901+#include <net/nl802154.h>
5902+#include <net/mac802154.h>
5903+#include <net/ieee802154.h>
5904+#include <net/ieee802154_netdev.h>
5905+
5906+#include "mac802154.h"
5907+#include "beacon_hash.h"
5908+
5909+/* Beacon frame format per specification is the followinf:
5910+ * Standard MAC frame header:
5911+ * FC (2) SEQ (1)
5912+ * Addressing (4-20)
5913+ * Beacon fields:
5914+ * <Superframe specification> (2)
5915+ * <GTS> (?)
5916+ * <Pending address> (?)
5917+ * <Beacon payload> (?)
5918+ * FCS (2)
5919+ *
5920+ * Superframe specification:
5921+ * bit Value
5922+ * 15 Association permit
5923+ * 14 PAN coordinator
5924+ * 13 Reserved
5925+ * 12 Battery life extension
5926+ * 8-11 Final CAP slot
5927+ * 4-7 Superframe order
5928+ * 0-3 Beacon order
5929+ *
5930+ * GTS:
5931+ * <GTS specification> (1)
5932+ * <GTS directions> (0-1)
5933+ * <GTS list> (?)
5934+ *
5935+ * Pending address:
5936+ * <Pending address specification> (1)
5937+ * <Pending address list (?)
5938+ *
5939+ * GTS specification:
5940+ * bit Value
5941+ * 7 GTS permit
5942+ * 3-6 Reserved
5943+ * 0-2 GTS descriptor count
5944+ *
5945+ * Pending address specification:
5946+ * bit Value
5947+ * 7 Reserved
5948+ * 4-6 Number of extended addresses pendinf
5949+ * 3 Reserved
5950+ * 0-2 Number of short addresses pending
5951+ * */
5952+
5953+#define IEEE802154_BEACON_SF_BO_BEACONLESS (15 << 0)
5954+#define IEEE802154_BEACON_SF_SO(x) ((x & 0xf) << 4)
5955+#define IEEE802154_BEACON_SF_SO_INACTIVE IEEE802154_BEACON_SF_SO(15)
5956+#define IEEE802154_BEACON_SF_PANCOORD (1 << 14)
5957+#define IEEE802154_BEACON_SF_CANASSOC (1 << 15)
5958+#define IEEE802154_BEACON_GTS_COUNT(x) (x << 0)
5959+#define IEEE802154_BEACON_GTS_PERMIT (1 << 7)
5960+#define IEEE802154_BEACON_PA_SHORT(x) ((x & 7) << 0)
5961+#define IEEE802154_BEACON_PA_LONG(x) ((x & 7) << 4)
5962+
5963+/* Flags parameter */
5964+#define IEEE802154_BEACON_FLAG_PANCOORD (1 << 0)
5965+#define IEEE802154_BEACON_FLAG_CANASSOC (1 << 1)
5966+#define IEEE802154_BEACON_FLAG_GTSPERMIT (1 << 2)
5967+
5968+struct mac802154_address_list {
5969+ struct list_head list;
5970+ struct ieee802154_addr addr;
5971+};
5972+
5973+/* Per spec; optimizations are needed */
5974+struct mac802154_pandsc {
5975+ struct list_head list;
5976+ struct ieee802154_addr addr; /* Contains panid */
5977+ int channel;
5978+ u16 sf;
5979+ bool gts_permit;
5980+ u8 lqi;
5981+/* FIXME: Aging of stored PAN descriptors is not decided yet,
5982+ * because no PAN descriptor storage is implemented yet */
5983+ u32 timestamp;
5984+};
5985+
5986+/*
5987+ * @dev device
5988+ * @addr destination address
5989+ * @saddr source address
5990+ * @buf beacon payload
5991+ * @len beacon payload size
5992+ * @pan_coord - if we're PAN coordinator while sending this frame
5993+ * @gts_permit - wheather we allow GTS requests
5994+ * @al address list to be provided in beacon
5995+ *
5996+ * TODO:
5997+ * For a beacon frame, the sequence number field shall specify a BSN.
5998+ * Each coordinator shall store its current
5999+ * BSN value in the MAC PIB attribute macBSN and initialize it to
6000+ * a random value.
6001+ * The algorithm for choosing a random number is out of the scope
6002+ * of this standard. The coordinator shall copy the value of the macBSN
6003+ * attribute into the sequence number field of a beacon frame,
6004+ * each time one is generated, and shall then increment macBSN by one.
6005+ *
6006+*/
6007+
6008+
6009+int mac802154_send_beacon(struct net_device *dev,
6010+ struct ieee802154_addr *saddr,
6011+ u16 pan_id, const u8 *buf, int len,
6012+ int flags, struct list_head *al)
6013+{
6014+ struct sk_buff *skb;
6015+ int err;
6016+ u16 sf;
6017+ u8 gts;
6018+ u8 pa_spec;
6019+ int addr16_cnt;
6020+ int addr64_cnt;
6021+ int hlen, tlen;
6022+ struct ieee802154_addr addr;
6023+
6024+ BUG_ON(dev->type != ARPHRD_IEEE802154);
6025+
6026+ hlen = LL_RESERVED_SPACE(dev);
6027+ tlen = dev->needed_tailroom;
6028+ skb = alloc_skb(len + hlen + tlen, GFP_ATOMIC);
6029+ if (!skb)
6030+ return -ENOMEM;
6031+
6032+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
6033+
6034+ skb_reset_network_header(skb);
6035+
6036+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_BEACON;
6037+ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_bsn(dev);
6038+
6039+ addr.addr_type = IEEE802154_ADDR_NONE;
6040+ err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &addr, saddr, len);
6041+ if (err < 0) {
6042+ kfree_skb(skb);
6043+ return err;
6044+ }
6045+ skb_reset_mac_header(skb);
6046+
6047+ /* Superframe */
6048+ sf = IEEE802154_BEACON_SF_BO_BEACONLESS;
6049+ sf |= IEEE802154_BEACON_SF_SO_INACTIVE;
6050+ if (flags & IEEE802154_BEACON_FLAG_PANCOORD)
6051+ sf |= IEEE802154_BEACON_SF_PANCOORD;
6052+
6053+ if (flags & IEEE802154_BEACON_FLAG_CANASSOC)
6054+ sf |= IEEE802154_BEACON_SF_CANASSOC;
6055+ memcpy(skb_put(skb, sizeof(sf)), &sf, sizeof(sf));
6056+
6057+ /* TODO GTS */
6058+ gts = 0;
6059+
6060+ if (flags & IEEE802154_BEACON_FLAG_GTSPERMIT)
6061+ gts |= IEEE802154_BEACON_GTS_PERMIT;
6062+ memcpy(skb_put(skb, sizeof(gts)), &gts, sizeof(gts));
6063+
6064+ /* FIXME pending address */
6065+ addr16_cnt = 0;
6066+ addr64_cnt = 0;
6067+
6068+ pa_spec = IEEE802154_BEACON_PA_LONG(addr64_cnt) |
6069+ IEEE802154_BEACON_PA_SHORT(addr16_cnt);
6070+ memcpy(skb_put(skb, sizeof(pa_spec)), &pa_spec, sizeof(pa_spec));
6071+
6072+ memcpy(skb_put(skb, len), buf, len);
6073+
6074+ skb->dev = dev;
6075+ skb->protocol = htons(ETH_P_IEEE802154);
6076+
6077+ return dev_queue_xmit(skb);
6078+}
6079+
6080+/* at entry to this function we need skb->data to point to start
6081+ * of beacon field and MAC frame already parsed into MAC_CB */
6082+
6083+static int parse_beacon_frame(struct sk_buff *skb, u8 *buf,
6084+ int *flags, struct list_head *al)
6085+{
6086+ int offt = 0;
6087+ u8 gts_spec;
6088+ u8 pa_spec;
6089+ struct mac802154_pandsc *pd;
6090+ u16 sf = skb->data[0] + (skb->data[1] << 8);
6091+
6092+ pd = kzalloc(sizeof(struct mac802154_pandsc), GFP_KERNEL);
6093+
6094+ /* Filling-up pre-parsed values */
6095+ pd->lqi = mac_cb(skb)->lqi;
6096+ pd->sf = sf;
6097+ /* FIXME: make sure we do it right */
6098+ memcpy(&pd->addr, &mac_cb(skb)->da, sizeof(struct ieee802154_addr));
6099+
6100+ /* Supplying our nitifiers with data */
6101+ ieee802154_nl_beacon_indic(skb->dev, pd->addr.pan_id,
6102+ pd->addr.short_addr);
6103+ /* FIXME: We don't cache PAN descriptors yet */
6104+ kfree(pd);
6105+
6106+ offt += 2;
6107+ gts_spec = skb->data[offt++];
6108+ /* FIXME !!! */
6109+ if ((gts_spec & 7) != 0) {
6110+ pr_debug("We still don't parse GTS part properly");
6111+ return -ENOTSUPP;
6112+ }
6113+ pa_spec = skb->data[offt++];
6114+ /* FIXME !!! */
6115+ if (pa_spec != 0) {
6116+ pr_debug("We still don't parse PA part properly");
6117+ return -ENOTSUPP;
6118+ }
6119+
6120+ *flags = 0;
6121+
6122+ if (sf & IEEE802154_BEACON_SF_PANCOORD)
6123+ *flags |= IEEE802154_BEACON_FLAG_PANCOORD;
6124+
6125+ if (sf & IEEE802154_BEACON_SF_CANASSOC)
6126+ *flags |= IEEE802154_BEACON_FLAG_CANASSOC;
6127+ BUG_ON(skb->len - offt < 0);
6128+ /* FIXME */
6129+ if (buf && (skb->len - offt > 0))
6130+ memcpy(buf, skb->data + offt, skb->len - offt);
6131+ return 0;
6132+}
6133+
6134+int mac802154_process_beacon(struct net_device *dev,
6135+ struct sk_buff *skb)
6136+{
6137+ int flags;
6138+ int ret;
6139+ ret = parse_beacon_frame(skb, NULL, &flags, NULL);
6140+
6141+ /* Here we have cb->sa = coordinator address, and PAN address */
6142+
6143+ if (ret < 0) {
6144+ ret = NET_RX_DROP;
6145+ goto fail;
6146+ }
6147+ dev_dbg(&dev->dev, "got beacon from pan %04x\n",
6148+ mac_cb(skb)->sa.pan_id);
6149+ mac802154_beacon_hash_add(&mac_cb(skb)->sa);
6150+ mac802154_beacon_hash_dump();
6151+ ret = NET_RX_SUCCESS;
6152+fail:
6153+ kfree_skb(skb);
6154+ return ret;
6155+}
6156+
6157diff --git a/net/mac802154/beacon_hash.c b/net/mac802154/beacon_hash.c
6158new file mode 100644
6159index 0000000..97fb987
6160--- /dev/null
6161@@ -0,0 +1,106 @@
6162+/*
6163+ * MAC beacon hash storage
6164+ *
6165+ * Copyright 2007, 2008 Siemens AG
6166+ *
6167+ * This program is free software; you can redistribute it and/or modify
6168+ * it under the terms of the GNU General Public License version 2
6169+ * as published by the Free Software Foundation.
6170+ *
6171+ * This program is distributed in the hope that it will be useful,
6172+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6173+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6174+ * GNU General Public License for more details.
6175+ *
6176+ * You should have received a copy of the GNU General Public License along
6177+ * with this program; if not, write to the Free Software Foundation, Inc.,
6178+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6179+ *
6180+ * Written by:
6181+ * Sergey Lapin <slapin@ossfans.org>
6182+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6183+ */
6184+
6185+#include <linux/slab.h>
6186+#include <linux/list.h>
6187+#include <linux/spinlock.h>
6188+
6189+#include <net/af_ieee802154.h>
6190+
6191+#include "beacon_hash.h"
6192+
6193+static struct hlist_head beacon_hash[IEEE802154_BEACON_HTABLE_SIZE];
6194+static DEFINE_SPINLOCK(beacon_hash_lock);
6195+
6196+static int beacon_hashfn(struct ieee802154_addr *coord_addr, u16 pan_addr)
6197+{
6198+ return pan_addr % IEEE802154_BEACON_HTABLE_SIZE;
6199+}
6200+
6201+static void __beacon_add_node(struct ieee802154_addr *coord_addr, u16 pan_addr)
6202+{
6203+ struct beacon_node *node =
6204+ kzalloc(sizeof(struct beacon_node), GFP_KERNEL);
6205+ struct hlist_head *list =
6206+ &beacon_hash[beacon_hashfn(coord_addr, pan_addr)];
6207+ memcpy(&node->coord_addr, coord_addr, sizeof(struct ieee802154_addr));
6208+ node->pan_addr = pan_addr;
6209+ INIT_HLIST_NODE(&node->list);
6210+ hlist_add_head(&node->list, list);
6211+}
6212+
6213+struct beacon_node *mac802154_beacon_find_pan(
6214+ struct ieee802154_addr *coord_addr, u16 pan_addr)
6215+{
6216+ struct hlist_head *list;
6217+ struct hlist_node *tmp;
6218+ list = &beacon_hash[beacon_hashfn(coord_addr, pan_addr)];
6219+ if (hlist_empty(list))
6220+ return NULL;
6221+ hlist_for_each(tmp, list) {
6222+ struct beacon_node *entry =
6223+ hlist_entry(tmp, struct beacon_node, list);
6224+ if (entry->pan_addr == pan_addr)
6225+ return entry;
6226+ }
6227+ return NULL;
6228+}
6229+
6230+void mac802154_beacon_hash_add(struct ieee802154_addr *coord_addr)
6231+{
6232+ if (!mac802154_beacon_find_pan(coord_addr, coord_addr->pan_id)) {
6233+ spin_lock(&beacon_hash_lock);
6234+ __beacon_add_node(coord_addr, coord_addr->pan_id);
6235+ spin_unlock(&beacon_hash_lock);
6236+ }
6237+}
6238+
6239+void mac802154_beacon_hash_del(struct ieee802154_addr *coord_addr)
6240+{
6241+ struct beacon_node *entry = mac802154_beacon_find_pan(coord_addr,
6242+ coord_addr->pan_id);
6243+ if (!entry)
6244+ return;
6245+ spin_lock(&beacon_hash_lock);
6246+ hlist_del(&entry->list);
6247+ spin_unlock(&beacon_hash_lock);
6248+ kfree(entry);
6249+}
6250+
6251+void mac802154_beacon_hash_dump(void)
6252+{
6253+ int i;
6254+ struct hlist_node *tmp;
6255+ pr_debug("beacon hash dump begin\n");
6256+ spin_lock(&beacon_hash_lock);
6257+ for (i = 0; i < IEEE802154_BEACON_HTABLE_SIZE; i++) {
6258+ struct beacon_node *entry;
6259+ hlist_for_each(tmp, &beacon_hash[i]) {
6260+ entry = hlist_entry(tmp, struct beacon_node, list);
6261+ pr_debug("PAN: %04x\n", entry->pan_addr);
6262+ }
6263+ }
6264+ spin_unlock(&beacon_hash_lock);
6265+ pr_debug("beacon hash dump end\n");
6266+}
6267+
6268diff --git a/net/mac802154/beacon_hash.h b/net/mac802154/beacon_hash.h
6269new file mode 100644
6270index 0000000..a732aa5
6271--- /dev/null
6272@@ -0,0 +1,41 @@
6273+/*
6274+ * MAC beacon hash storage
6275+ *
6276+ * Copyright 2007, 2008 Siemens AG
6277+ *
6278+ * This program is free software; you can redistribute it and/or modify
6279+ * it under the terms of the GNU General Public License version 2
6280+ * as published by the Free Software Foundation.
6281+ *
6282+ * This program is distributed in the hope that it will be useful,
6283+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6284+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6285+ * GNU General Public License for more details.
6286+ *
6287+ * You should have received a copy of the GNU General Public License along
6288+ * with this program; if not, write to the Free Software Foundation, Inc.,
6289+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6290+ *
6291+ * Written by:
6292+ * Sergey Lapin <slapin@ossfans.org>
6293+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6294+ */
6295+
6296+#ifndef IEEE802154_BEACON_HASH_H
6297+#define IEEE802154_BEACON_HASH_H
6298+
6299+#define IEEE802154_BEACON_HTABLE_SIZE 256
6300+
6301+struct beacon_node {
6302+ struct hlist_node list;
6303+ struct ieee802154_addr coord_addr;
6304+ u16 pan_addr;
6305+};
6306+struct beacon_node *mac802154_beacon_find_pan(
6307+ struct ieee802154_addr *coord_addr,
6308+ u16 pan_addr);
6309+void mac802154_beacon_hash_add(struct ieee802154_addr *coord_addr);
6310+void mac802154_beacon_hash_del(struct ieee802154_addr *coord_addr);
6311+void mac802154_beacon_hash_dump(void);
6312+#endif
6313+
6314diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
6315new file mode 100644
6316index 0000000..f35245d
6317--- /dev/null
6318@@ -0,0 +1,126 @@
6319+/*
6320+ * Copyright (C) 2007, 2008, 2009 Siemens AG
6321+ *
6322+ * This program is free software; you can redistribute it and/or modify
6323+ * it under the terms of the GNU General Public License version 2
6324+ * as published by the Free Software Foundation.
6325+ *
6326+ * This program is distributed in the hope that it will be useful,
6327+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6328+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6329+ * GNU General Public License for more details.
6330+ *
6331+ * You should have received a copy of the GNU General Public License along
6332+ * with this program; if not, write to the Free Software Foundation, Inc.,
6333+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6334+ *
6335+ * Written by:
6336+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
6337+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
6338+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6339+ */
6340+#ifndef MAC802154_H
6341+#define MAC802154_H
6342+
6343+#include <linux/spinlock.h>
6344+
6345+struct mac802154_priv {
6346+ struct ieee802154_dev hw;
6347+ struct ieee802154_ops *ops;
6348+
6349+ struct wpan_phy *phy;
6350+
6351+ int open_count;
6352+ /* As in mac80211 slaves list is modified:
6353+ * 1) under the RTNL
6354+ * 2) protected by slaves_mtx;
6355+ * 3) in an RCU manner
6356+ *
6357+ * So atomic readers can use any of this protection methods
6358+ */
6359+ struct list_head slaves;
6360+ struct mutex slaves_mtx;
6361+ /* This one is used for scanning and other
6362+ * jobs not to be interfered with serial driver */
6363+ struct workqueue_struct *dev_workqueue;
6364+
6365+ /*
6366+ * These flags are also modified under slaves_mtx and RTNL,
6367+ * so you can read them using any of protection methods.
6368+ */
6369+ /* SoftMAC device is registered and running. One can add subinterfaces. */
6370+ unsigned running: 1;
6371+};
6372+
6373+#define mac802154_to_priv(_hw) container_of(_hw, struct mac802154_priv, hw)
6374+
6375+struct mac802154_wpan_mib {
6376+ spinlock_t mib_lock;
6377+
6378+ u16 pan_id;
6379+ u16 short_addr;
6380+
6381+ u8 chan;
6382+ u8 page;
6383+
6384+ /* MAC BSN field */
6385+ u8 bsn;
6386+ /* MAC BSN field */
6387+ u8 dsn;
6388+};
6389+
6390+struct mac802154_sub_if_data {
6391+ struct list_head list; /* the ieee802154_priv->slaves list */
6392+
6393+ struct mac802154_priv *hw;
6394+ struct net_device *dev;
6395+
6396+ int type;
6397+
6398+ spinlock_t mib_lock;
6399+
6400+ u16 pan_id;
6401+ u16 short_addr;
6402+
6403+ u8 chan;
6404+ u8 page;
6405+
6406+ /* MAC BSN field */
6407+ u8 bsn;
6408+ /* MAC DSN field */
6409+ u8 dsn;
6410+};
6411+
6412+struct ieee802154_addr;
6413+
6414+extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
6415+extern struct simple_mlme_ops mac802154_mlme_simple;
6416+
6417+int mac802154_mlme_scan_req(struct net_device *dev,
6418+ u8 type, u32 channels, u8 page, u8 duration);
6419+
6420+int mac802154_process_cmd(struct net_device *dev, struct sk_buff *skb);
6421+int mac802154_process_beacon(struct net_device *dev, struct sk_buff *skb);
6422+int mac802154_send_beacon(struct net_device *dev,
6423+ struct ieee802154_addr *saddr,
6424+ u16 pan_id, const u8 *buf, int len,
6425+ int flags, struct list_head *al);
6426+int mac802154_send_beacon_req(struct net_device *dev);
6427+
6428+struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev);
6429+
6430+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb);
6431+void mac802154_monitor_setup(struct net_device *dev);
6432+
6433+void mac802154_smacs_rx(struct mac802154_priv *priv, struct sk_buff *skb);
6434+void mac802154_smac_setup(struct net_device *dev);
6435+
6436+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb);
6437+void mac802154_wpan_setup(struct net_device *dev);
6438+
6439+int mac802154_slave_open(struct net_device *dev);
6440+int mac802154_slave_close(struct net_device *dev);
6441+
6442+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
6443+ u8 page, u8 chan);
6444+#endif
6445diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
6446new file mode 100644
6447index 0000000..e92947a
6448--- /dev/null
6449@@ -0,0 +1,365 @@
6450+/*
6451+ * MAC commands interface
6452+ *
6453+ * Copyright 2007, 2008 Siemens AG
6454+ *
6455+ * This program is free software; you can redistribute it and/or modify
6456+ * it under the terms of the GNU General Public License version 2
6457+ * as published by the Free Software Foundation.
6458+ *
6459+ * This program is distributed in the hope that it will be useful,
6460+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6461+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6462+ * GNU General Public License for more details.
6463+ *
6464+ * You should have received a copy of the GNU General Public License along
6465+ * with this program; if not, write to the Free Software Foundation, Inc.,
6466+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6467+ *
6468+ * Written by:
6469+ * Sergey Lapin <slapin@ossfans.org>
6470+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6471+ */
6472+
6473+#include <linux/kernel.h>
6474+#include <linux/skbuff.h>
6475+#include <linux/if_arp.h>
6476+#include <net/af_ieee802154.h>
6477+#include <net/mac802154.h>
6478+#include <net/ieee802154.h>
6479+#include <net/ieee802154_netdev.h>
6480+#include <net/nl802154.h>
6481+
6482+#include "mac802154.h"
6483+#include "mib.h"
6484+
6485+static int mac802154_cmd_beacon_req(struct sk_buff *skb)
6486+{
6487+ struct ieee802154_addr saddr; /* jeez */
6488+ int flags = 0;
6489+ u16 shortaddr;
6490+
6491+ if (skb->len != 1)
6492+ return -EINVAL;
6493+
6494+ if (skb->pkt_type != PACKET_BROADCAST)
6495+ return 0;
6496+
6497+ /* Checking if we're really PAN coordinator
6498+ * before sending beacons */
6499+ if (!(skb->dev->priv_flags & IFF_IEEE802154_COORD))
6500+ return 0;
6501+
6502+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE ||
6503+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_SHORT ||
6504+ mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST ||
6505+ mac_cb(skb)->da.short_addr != IEEE802154_ADDR_BROADCAST)
6506+ return -EINVAL;
6507+
6508+ shortaddr = mac802154_dev_get_short_addr(skb->dev);
6509+ if (shortaddr != IEEE802154_ADDR_BROADCAST &&
6510+ shortaddr != IEEE802154_ADDR_UNDEF) {
6511+ saddr.addr_type = IEEE802154_ADDR_SHORT;
6512+ saddr.short_addr = shortaddr;
6513+ } else {
6514+ saddr.addr_type = IEEE802154_ADDR_LONG;
6515+ memcpy(saddr.hwaddr, skb->dev->dev_addr, IEEE802154_ADDR_LEN);
6516+ }
6517+ saddr.pan_id = mac802154_dev_get_pan_id(skb->dev);
6518+
6519+
6520+ /* 7 bytes of MHR and 1 byte of command frame identifier
6521+ * We have no information in this command to proceed with.
6522+ * we need to submit beacon as answer to this. */
6523+
6524+ return mac802154_send_beacon(skb->dev, &saddr,
6525+ ieee802154_mlme_ops(skb->dev)->get_pan_id(skb->dev),
6526+ NULL, 0, flags, NULL);
6527+}
6528+
6529+static int mac802154_cmd_assoc_req(struct sk_buff *skb)
6530+{
6531+ u8 cap;
6532+
6533+ if (skb->len != 2)
6534+ return -EINVAL;
6535+
6536+ if (skb->pkt_type != PACKET_HOST)
6537+ return 0;
6538+
6539+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
6540+ mac_cb(skb)->sa.pan_id != IEEE802154_PANID_BROADCAST)
6541+ return -EINVAL;
6542+
6543+ /*
6544+ * FIXME: check that we allow incoming ASSOC requests
6545+ * by consulting MIB
6546+ */
6547+
6548+ cap = skb->data[1];
6549+
6550+ return ieee802154_nl_assoc_indic(skb->dev, &mac_cb(skb)->sa, cap);
6551+}
6552+
6553+static int mac802154_cmd_assoc_resp(struct sk_buff *skb)
6554+{
6555+ u8 status;
6556+ u16 short_addr;
6557+
6558+ if (skb->len != 4)
6559+ return -EINVAL;
6560+
6561+ if (skb->pkt_type != PACKET_HOST)
6562+ return 0;
6563+
6564+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
6565+ mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
6566+ !(mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN))
6567+ return -EINVAL;
6568+
6569+ /* FIXME: check that we requested association ? */
6570+
6571+ status = skb->data[3];
6572+ short_addr = skb->data[1] | (skb->data[2] << 8);
6573+ pr_info("Received ASSOC-RESP status %x, addr %hx\n", status,
6574+ short_addr);
6575+ if (status) {
6576+ mac802154_dev_set_short_addr(skb->dev,
6577+ IEEE802154_ADDR_BROADCAST);
6578+ mac802154_dev_set_pan_id(skb->dev,
6579+ IEEE802154_PANID_BROADCAST);
6580+ } else
6581+ mac802154_dev_set_short_addr(skb->dev, short_addr);
6582+
6583+ return ieee802154_nl_assoc_confirm(skb->dev, short_addr, status);
6584+}
6585+
6586+static int mac802154_cmd_disassoc_notify(struct sk_buff *skb)
6587+{
6588+ u8 reason;
6589+
6590+ if (skb->len != 2)
6591+ return -EINVAL;
6592+
6593+ if (skb->pkt_type != PACKET_HOST)
6594+ return 0;
6595+
6596+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_LONG ||
6597+ (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_LONG &&
6598+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_SHORT) ||
6599+ mac_cb(skb)->sa.pan_id != mac_cb(skb)->da.pan_id)
6600+ return -EINVAL;
6601+
6602+ reason = skb->data[1];
6603+
6604+ /* FIXME: checks if this was our coordinator and the disassoc us */
6605+ /* FIXME: if we device, one should receive ->da and not ->sa */
6606+ /* FIXME: the status should also help */
6607+
6608+ return ieee802154_nl_disassoc_indic(skb->dev, &mac_cb(skb)->sa,
6609+ reason);
6610+}
6611+
6612+int mac802154_process_cmd(struct net_device *dev, struct sk_buff *skb)
6613+{
6614+ u8 cmd;
6615+
6616+ if (skb->len < 1) {
6617+ pr_warning("Uncomplete command frame!\n");
6618+ goto drop;
6619+ }
6620+
6621+ cmd = *(skb->data);
6622+ pr_debug("Command %02x on device %s\n", cmd, dev->name);
6623+
6624+ switch (cmd) {
6625+ case IEEE802154_CMD_ASSOCIATION_REQ:
6626+ mac802154_cmd_assoc_req(skb);
6627+ break;
6628+ case IEEE802154_CMD_ASSOCIATION_RESP:
6629+ mac802154_cmd_assoc_resp(skb);
6630+ break;
6631+ case IEEE802154_CMD_DISASSOCIATION_NOTIFY:
6632+ mac802154_cmd_disassoc_notify(skb);
6633+ break;
6634+ case IEEE802154_CMD_BEACON_REQ:
6635+ mac802154_cmd_beacon_req(skb);
6636+ break;
6637+ default:
6638+ pr_debug("Frame type is not supported yet\n");
6639+ goto drop;
6640+ }
6641+
6642+
6643+ kfree_skb(skb);
6644+ return NET_RX_SUCCESS;
6645+
6646+drop:
6647+ kfree_skb(skb);
6648+ return NET_RX_DROP;
6649+}
6650+
6651+static int mac802154_send_cmd(struct net_device *dev,
6652+ struct ieee802154_addr *addr, struct ieee802154_addr *saddr,
6653+ const u8 *buf, int len)
6654+{
6655+ struct sk_buff *skb;
6656+ int hlen, tlen;
6657+ int err;
6658+
6659+ BUG_ON(dev->type != ARPHRD_IEEE802154);
6660+
6661+ hlen = LL_RESERVED_SPACE(dev);
6662+ tlen = dev->needed_tailroom;
6663+ skb = alloc_skb(len + hlen + tlen, GFP_KERNEL);
6664+ if (!skb)
6665+ return -ENOMEM;
6666+
6667+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
6668+
6669+ skb_reset_network_header(skb);
6670+
6671+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_MAC_CMD | MAC_CB_FLAG_ACKREQ;
6672+ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
6673+ err = dev_hard_header(skb, dev, ETH_P_IEEE802154, addr, saddr, len);
6674+ if (err < 0) {
6675+ kfree_skb(skb);
6676+ return err;
6677+ }
6678+
6679+ skb_reset_mac_header(skb);
6680+ memcpy(skb_put(skb, len), buf, len);
6681+
6682+ skb->dev = dev;
6683+ skb->protocol = htons(ETH_P_IEEE802154);
6684+
6685+ return dev_queue_xmit(skb);
6686+}
6687+
6688+int mac802154_send_beacon_req(struct net_device *dev)
6689+{
6690+ struct ieee802154_addr addr;
6691+ struct ieee802154_addr saddr;
6692+ u8 cmd = IEEE802154_CMD_BEACON_REQ;
6693+ addr.addr_type = IEEE802154_ADDR_SHORT;
6694+ addr.short_addr = IEEE802154_ADDR_BROADCAST;
6695+ addr.pan_id = IEEE802154_PANID_BROADCAST;
6696+ saddr.addr_type = IEEE802154_ADDR_NONE;
6697+ return mac802154_send_cmd(dev, &addr, &saddr, &cmd, 1);
6698+}
6699+
6700+
6701+static int mac802154_mlme_assoc_req(struct net_device *dev,
6702+ struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
6703+{
6704+ struct ieee802154_addr saddr;
6705+ u8 buf[2];
6706+ int pos = 0;
6707+
6708+ saddr.addr_type = IEEE802154_ADDR_LONG;
6709+ saddr.pan_id = IEEE802154_PANID_BROADCAST;
6710+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
6711+
6712+
6713+ /* FIXME: set PIB/MIB info */
6714+ mac802154_dev_set_pan_id(dev, addr->pan_id);
6715+ mac802154_dev_set_page_channel(dev, page, channel);
6716+ mac802154_dev_set_ieee_addr(dev);
6717+
6718+ buf[pos++] = IEEE802154_CMD_ASSOCIATION_REQ;
6719+ buf[pos++] = cap;
6720+
6721+ return mac802154_send_cmd(dev, addr, &saddr, buf, pos);
6722+}
6723+
6724+static int mac802154_mlme_assoc_resp(struct net_device *dev,
6725+ struct ieee802154_addr *addr, u16 short_addr, u8 status)
6726+{
6727+ struct ieee802154_addr saddr;
6728+ u8 buf[4];
6729+ int pos = 0;
6730+
6731+ saddr.addr_type = IEEE802154_ADDR_LONG;
6732+ saddr.pan_id = addr->pan_id;
6733+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
6734+
6735+ buf[pos++] = IEEE802154_CMD_ASSOCIATION_RESP;
6736+ buf[pos++] = short_addr;
6737+ buf[pos++] = short_addr >> 8;
6738+ buf[pos++] = status;
6739+
6740+ return mac802154_send_cmd(dev, addr, &saddr, buf, pos);
6741+}
6742+
6743+static int mac802154_mlme_disassoc_req(struct net_device *dev,
6744+ struct ieee802154_addr *addr, u8 reason)
6745+{
6746+ struct ieee802154_addr saddr;
6747+ u8 buf[2];
6748+ int pos = 0;
6749+ int ret;
6750+
6751+ saddr.addr_type = IEEE802154_ADDR_LONG;
6752+ saddr.pan_id = addr->pan_id;
6753+ memcpy(saddr.hwaddr, dev->dev_addr, IEEE802154_ADDR_LEN);
6754+
6755+ buf[pos++] = IEEE802154_CMD_DISASSOCIATION_NOTIFY;
6756+ buf[pos++] = reason;
6757+
6758+ ret = mac802154_send_cmd(dev, addr, &saddr, buf, pos);
6759+
6760+ /* FIXME: this should be after the ack receved */
6761+ mac802154_dev_set_pan_id(dev, 0xffff);
6762+ mac802154_dev_set_short_addr(dev, 0xffff);
6763+ ieee802154_nl_disassoc_confirm(dev, 0x00);
6764+
6765+ return ret;
6766+}
6767+
6768+static int mac802154_mlme_start_req(struct net_device *dev,
6769+ struct ieee802154_addr *addr,
6770+ u8 channel, u8 page,
6771+ u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
6772+ u8 coord_realign)
6773+{
6774+ BUG_ON(addr->addr_type != IEEE802154_ADDR_SHORT);
6775+
6776+ mac802154_dev_set_pan_id(dev, addr->pan_id);
6777+ mac802154_dev_set_short_addr(dev, addr->short_addr);
6778+ mac802154_dev_set_ieee_addr(dev);
6779+ mac802154_dev_set_page_channel(dev, page, channel);
6780+
6781+ /*
6782+ * FIXME: add validation for unused parameters to be sane
6783+ * for SoftMAC
6784+ */
6785+
6786+ if (pan_coord)
6787+ dev->priv_flags |= IFF_IEEE802154_COORD;
6788+ else
6789+ dev->priv_flags &= ~IFF_IEEE802154_COORD;
6790+
6791+ mac802154_dev_set_pan_coord(dev);
6792+ ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
6793+
6794+ return 0;
6795+}
6796+
6797+struct ieee802154_mlme_ops mac802154_mlme_wpan = {
6798+ .assoc_req = mac802154_mlme_assoc_req,
6799+ .assoc_resp = mac802154_mlme_assoc_resp,
6800+ .disassoc_req = mac802154_mlme_disassoc_req,
6801+ .start_req = mac802154_mlme_start_req,
6802+ .scan_req = mac802154_mlme_scan_req,
6803+
6804+ .wpan_ops.get_phy = mac802154_get_phy,
6805+
6806+ .get_pan_id = mac802154_dev_get_pan_id,
6807+ .get_short_addr = mac802154_dev_get_short_addr,
6808+ .get_dsn = mac802154_dev_get_dsn,
6809+ .get_bsn = mac802154_dev_get_bsn,
6810+};
6811+
6812+struct simple_mlme_ops mac802154_mlme_simple = {
6813+ .get_phy = mac802154_get_phy,
6814+};
6815diff --git a/net/mac802154/main.c b/net/mac802154/main.c
6816new file mode 100644
6817index 0000000..f2acbcb
6818--- /dev/null
6819@@ -0,0 +1,283 @@
6820+/*
6821+ * Copyright (C) 2007, 2008, 2009 Siemens AG
6822+ *
6823+ * This program is free software; you can redistribute it and/or modify
6824+ * it under the terms of the GNU General Public License version 2
6825+ * as published by the Free Software Foundation.
6826+ *
6827+ * This program is distributed in the hope that it will be useful,
6828+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6829+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6830+ * GNU General Public License for more details.
6831+ *
6832+ * You should have received a copy of the GNU General Public License along
6833+ * with this program; if not, write to the Free Software Foundation, Inc.,
6834+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6835+ *
6836+ */
6837+
6838+#include <linux/kernel.h>
6839+#include <linux/netdevice.h>
6840+#include <linux/if_arp.h>
6841+#include <linux/nl802154.h>
6842+#include <linux/module.h>
6843+#include <net/route.h>
6844+
6845+#include <net/mac802154.h>
6846+#include <net/wpan-phy.h>
6847+
6848+#include "mac802154.h"
6849+#include "mib.h"
6850+
6851+int mac802154_slave_open(struct net_device *dev)
6852+{
6853+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
6854+ int res = 0;
6855+
6856+ if (priv->hw->open_count++ == 0) {
6857+ res = priv->hw->ops->start(&priv->hw->hw);
6858+ WARN_ON(res);
6859+ if (res)
6860+ goto err;
6861+ }
6862+
6863+ if (priv->hw->ops->ieee_addr) {
6864+ res = priv->hw->ops->ieee_addr(&priv->hw->hw, dev->dev_addr);
6865+ WARN_ON(res);
6866+ if (res)
6867+ goto err;
6868+ mac802154_dev_set_ieee_addr(dev);
6869+ }
6870+
6871+ netif_start_queue(dev);
6872+ return 0;
6873+err:
6874+ priv->hw->open_count--;
6875+
6876+ return res;
6877+}
6878+
6879+int mac802154_slave_close(struct net_device *dev)
6880+{
6881+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
6882+
6883+ dev->priv_flags &= ~IFF_IEEE802154_COORD;
6884+
6885+ netif_stop_queue(dev);
6886+
6887+ if ((--priv->hw->open_count) == 0)
6888+ priv->hw->ops->stop(&priv->hw->hw);
6889+
6890+ return 0;
6891+}
6892+
6893+
6894+static int mac802154_netdev_register(struct wpan_phy *phy,
6895+ struct net_device *dev)
6896+{
6897+ struct mac802154_sub_if_data *priv;
6898+ struct mac802154_priv *ipriv;
6899+ int err;
6900+
6901+ ipriv = wpan_phy_priv(phy);
6902+
6903+ priv = netdev_priv(dev);
6904+ priv->dev = dev;
6905+ priv->hw = ipriv;
6906+
6907+ dev->needed_headroom = ipriv->hw.extra_tx_headroom;
6908+
6909+ SET_NETDEV_DEV(dev, &ipriv->phy->dev);
6910+
6911+ mutex_lock(&ipriv->slaves_mtx);
6912+ if (!ipriv->running) {
6913+ mutex_unlock(&ipriv->slaves_mtx);
6914+ return -ENODEV;
6915+ }
6916+ mutex_unlock(&ipriv->slaves_mtx);
6917+
6918+ err = register_netdev(dev);
6919+ if (err < 0)
6920+ return err;
6921+
6922+ rtnl_lock();
6923+ mutex_lock(&ipriv->slaves_mtx);
6924+ list_add_tail_rcu(&priv->list, &ipriv->slaves);
6925+ mutex_unlock(&ipriv->slaves_mtx);
6926+ rtnl_unlock();
6927+
6928+ return 0;
6929+}
6930+
6931+static void mac802154_del_iface(struct wpan_phy *phy,
6932+ struct net_device *dev)
6933+{
6934+ struct mac802154_sub_if_data *sdata;
6935+ ASSERT_RTNL();
6936+
6937+ sdata = netdev_priv(dev);
6938+
6939+ BUG_ON(sdata->hw->phy != phy);
6940+
6941+ mutex_lock(&sdata->hw->slaves_mtx);
6942+ list_del_rcu(&sdata->list);
6943+ mutex_unlock(&sdata->hw->slaves_mtx);
6944+
6945+ synchronize_rcu();
6946+ unregister_netdevice(sdata->dev);
6947+}
6948+
6949+static struct net_device *mac802154_add_iface(struct wpan_phy *phy,
6950+ const char *name, int type)
6951+{
6952+ struct net_device *dev;
6953+ int err = -ENOMEM;
6954+
6955+ switch (type) {
6956+ case IEEE802154_DEV_WPAN:
6957+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
6958+ name, mac802154_wpan_setup);
6959+ break;
6960+ case IEEE802154_DEV_MONITOR:
6961+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
6962+ name, mac802154_monitor_setup);
6963+ break;
6964+ case IEEE802154_DEV_SMAC:
6965+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
6966+ name, mac802154_smac_setup);
6967+ break;
6968+ default:
6969+ dev = NULL;
6970+ err = -EINVAL;
6971+ break;
6972+ }
6973+ if (!dev)
6974+ goto err;
6975+
6976+
6977+ err = mac802154_netdev_register(phy, dev);
6978+
6979+ if (err)
6980+ goto err_free;
6981+
6982+ dev_hold(dev); /* we return a device w/ incremented refcount */
6983+ return dev;
6984+
6985+err_free:
6986+ free_netdev(dev);
6987+err:
6988+ return ERR_PTR(err);
6989+}
6990+
6991+
6992+struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
6993+ struct ieee802154_ops *ops)
6994+{
6995+ struct wpan_phy *phy;
6996+ struct mac802154_priv *priv;
6997+
6998+ phy = wpan_phy_alloc(ALIGN(sizeof(*priv), NETDEV_ALIGN) + priv_size);
6999+ if (!phy) {
7000+ printk(KERN_ERR
7001+ "Failure to initialize master IEEE802154 device\n");
7002+ return NULL;
7003+ }
7004+
7005+ priv = wpan_phy_priv(phy);
7006+ priv->hw.phy = priv->phy = phy;
7007+
7008+ priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
7009+
7010+ BUG_ON(!ops);
7011+ BUG_ON(!ops->xmit);
7012+ BUG_ON(!ops->ed);
7013+ BUG_ON(!ops->start);
7014+ BUG_ON(!ops->stop);
7015+
7016+ priv->ops = ops;
7017+
7018+ INIT_LIST_HEAD(&priv->slaves);
7019+ mutex_init(&priv->slaves_mtx);
7020+
7021+ return &priv->hw;
7022+}
7023+EXPORT_SYMBOL(ieee802154_alloc_device);
7024+
7025+void ieee802154_free_device(struct ieee802154_dev *hw)
7026+{
7027+ struct mac802154_priv *priv = mac802154_to_priv(hw);
7028+
7029+ BUG_ON(!list_empty(&priv->slaves));
7030+
7031+ wpan_phy_free(priv->phy);
7032+}
7033+EXPORT_SYMBOL(ieee802154_free_device);
7034+
7035+int ieee802154_register_device(struct ieee802154_dev *dev)
7036+{
7037+ struct mac802154_priv *priv = mac802154_to_priv(dev);
7038+ int rc;
7039+
7040+ priv->dev_workqueue =
7041+ create_singlethread_workqueue(wpan_phy_name(priv->phy));
7042+ if (!priv->dev_workqueue) {
7043+ rc = -ENOMEM;
7044+ goto out;
7045+ }
7046+
7047+ wpan_phy_set_dev(priv->phy, priv->hw.parent);
7048+
7049+ priv->phy->add_iface = mac802154_add_iface;
7050+ priv->phy->del_iface = mac802154_del_iface;
7051+
7052+ rc = wpan_phy_register(priv->phy);
7053+ if (rc < 0)
7054+ goto out_wq;
7055+
7056+ rtnl_lock();
7057+ mutex_lock(&priv->slaves_mtx);
7058+ priv->running = 1;
7059+ mutex_unlock(&priv->slaves_mtx);
7060+ rtnl_unlock();
7061+
7062+ return 0;
7063+
7064+out_wq:
7065+ destroy_workqueue(priv->dev_workqueue);
7066+out:
7067+ return rc;
7068+}
7069+EXPORT_SYMBOL(ieee802154_register_device);
7070+
7071+void ieee802154_unregister_device(struct ieee802154_dev *dev)
7072+{
7073+ struct mac802154_priv *priv = mac802154_to_priv(dev);
7074+ struct mac802154_sub_if_data *sdata, *next;
7075+
7076+
7077+ flush_workqueue(priv->dev_workqueue);
7078+ destroy_workqueue(priv->dev_workqueue);
7079+
7080+ rtnl_lock();
7081+
7082+ mutex_lock(&priv->slaves_mtx);
7083+ priv->running = 0;
7084+ mutex_unlock(&priv->slaves_mtx);
7085+
7086+ list_for_each_entry_safe(sdata, next, &priv->slaves, list) {
7087+ mutex_lock(&sdata->hw->slaves_mtx);
7088+ list_del(&sdata->list);
7089+ mutex_unlock(&sdata->hw->slaves_mtx);
7090+
7091+ unregister_netdevice(sdata->dev);
7092+ }
7093+
7094+ rtnl_unlock();
7095+
7096+ wpan_phy_unregister(priv->phy);
7097+}
7098+EXPORT_SYMBOL(ieee802154_unregister_device);
7099+
7100+MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
7101+MODULE_LICENSE("GPL v2");
7102+
7103diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
7104new file mode 100644
7105index 0000000..23871df
7106--- /dev/null
7107@@ -0,0 +1,249 @@
7108+/*
7109+ * Copyright 2007, 2008, 2009 Siemens AG
7110+ *
7111+ * This program is free software; you can redistribute it and/or modify
7112+ * it under the terms of the GNU General Public License version 2
7113+ * as published by the Free Software Foundation.
7114+ *
7115+ * This program is distributed in the hope that it will be useful,
7116+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7117+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7118+ * GNU General Public License for more details.
7119+ *
7120+ * You should have received a copy of the GNU General Public License along
7121+ * with this program; if not, write to the Free Software Foundation, Inc.,
7122+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7123+ *
7124+ * Written by:
7125+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
7126+ * Sergey Lapin <slapin@ossfans.org>
7127+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
7128+ */
7129+
7130+#include <linux/if_arp.h>
7131+
7132+#include <net/mac802154.h>
7133+#include <net/wpan-phy.h>
7134+
7135+#include "mac802154.h"
7136+#include "mib.h"
7137+
7138+struct phy_chan_notify_work {
7139+ struct work_struct work;
7140+ struct net_device *dev;
7141+};
7142+
7143+struct hw_addr_filt_notify_work {
7144+ struct work_struct work;
7145+ struct net_device *dev;
7146+ unsigned long changed;
7147+};
7148+
7149+static void hw_addr_notify(struct work_struct *work)
7150+{
7151+ struct hw_addr_filt_notify_work *nw = container_of(work,
7152+ struct hw_addr_filt_notify_work, work);
7153+ struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
7154+ int res;
7155+
7156+ res = hw->ops->set_hw_addr_filt(&hw->hw,
7157+ &hw->hw.hw_filt, nw->changed);
7158+ if (res)
7159+ pr_debug("%s: failed changed mask %lx\n",
7160+ __func__, nw->changed);
7161+
7162+ kfree(nw);
7163+
7164+ return;
7165+}
7166+
7167+static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
7168+{
7169+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7170+ struct hw_addr_filt_notify_work *work;
7171+
7172+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
7173+ if (!work)
7174+ return;
7175+
7176+ INIT_WORK(&work->work, hw_addr_notify);
7177+ work->dev = dev;
7178+ work->changed = changed;
7179+ queue_work(priv->hw->dev_workqueue, &work->work);
7180+
7181+ return;
7182+}
7183+
7184+static void phy_chan_notify(struct work_struct *work)
7185+{
7186+ struct phy_chan_notify_work *nw = container_of(work,
7187+ struct phy_chan_notify_work, work);
7188+ struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
7189+ struct mac802154_sub_if_data *priv = netdev_priv(nw->dev);
7190+ int res;
7191+
7192+ res = hw->ops->set_channel(&hw->hw, priv->page, priv->chan);
7193+ if (res)
7194+ pr_debug("set_channel failed\n");
7195+
7196+ kfree(nw);
7197+
7198+ return;
7199+}
7200+
7201+u16 mac802154_dev_get_pan_id(const struct net_device *dev)
7202+{
7203+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7204+ u16 ret;
7205+
7206+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7207+
7208+ spin_lock_bh(&priv->mib_lock);
7209+ ret = priv->pan_id;
7210+ spin_unlock_bh(&priv->mib_lock);
7211+
7212+ return ret;
7213+}
7214+
7215+u16 mac802154_dev_get_short_addr(const struct net_device *dev)
7216+{
7217+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7218+ u16 ret;
7219+
7220+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7221+
7222+ spin_lock_bh(&priv->mib_lock);
7223+ ret = priv->short_addr;
7224+ spin_unlock_bh(&priv->mib_lock);
7225+
7226+ return ret;
7227+}
7228+
7229+void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
7230+{
7231+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7232+
7233+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7234+
7235+ spin_lock_bh(&priv->mib_lock);
7236+ priv->pan_id = val;
7237+ spin_unlock_bh(&priv->mib_lock);
7238+
7239+ if (priv->hw->ops->set_hw_addr_filt &&
7240+ (priv->hw->hw.hw_filt.pan_id != priv->pan_id)) {
7241+ priv->hw->hw.hw_filt.pan_id = priv->pan_id;
7242+ set_hw_addr_filt(dev, IEEE802515_PANID_CHANGED);
7243+ }
7244+}
7245+
7246+void mac802154_dev_set_pan_coord(struct net_device *dev)
7247+{
7248+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7249+ int pan_coord = !!(dev->priv_flags & IFF_IEEE802154_COORD);
7250+
7251+ if (priv->hw->ops->set_hw_addr_filt &&
7252+ (priv->hw->hw.hw_filt.pan_coord != pan_coord)) {
7253+ priv->hw->hw.hw_filt.pan_coord = pan_coord;
7254+ set_hw_addr_filt(dev, IEEE802515_PANC_CHANGED);
7255+ }
7256+}
7257+
7258+void mac802154_dev_set_short_addr(struct net_device *dev, u16 val)
7259+{
7260+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7261+
7262+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7263+
7264+ spin_lock_bh(&priv->mib_lock);
7265+ priv->short_addr = val;
7266+ spin_unlock_bh(&priv->mib_lock);
7267+
7268+ if (priv->hw->ops->set_hw_addr_filt &&
7269+ (priv->hw->hw.hw_filt.short_addr != priv->short_addr)) {
7270+ priv->hw->hw.hw_filt.short_addr = priv->short_addr;
7271+ set_hw_addr_filt(dev, IEEE802515_SADDR_CHANGED);
7272+ }
7273+}
7274+
7275+void mac802154_dev_set_ieee_addr(struct net_device *dev)
7276+{
7277+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7278+
7279+ if (priv->hw->ops->set_hw_addr_filt &&
7280+ memcmp(priv->hw->hw.hw_filt.ieee_addr,
7281+ dev->dev_addr, IEEE802154_ALEN)) {
7282+ memcpy(priv->hw->hw.hw_filt.ieee_addr,
7283+ dev->dev_addr, IEEE802154_ALEN);
7284+ set_hw_addr_filt(dev, IEEE802515_IEEEADDR_CHANGED);
7285+ }
7286+}
7287+
7288+void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
7289+{
7290+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7291+ struct phy_chan_notify_work *work;
7292+
7293+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7294+
7295+ spin_lock_bh(&priv->mib_lock);
7296+ priv->page = page;
7297+ priv->chan = chan;
7298+ spin_unlock_bh(&priv->mib_lock);
7299+
7300+ if (priv->hw->phy->current_channel != priv->chan ||
7301+ priv->hw->phy->current_page != priv->page) {
7302+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
7303+ if (!work)
7304+ return;
7305+
7306+ INIT_WORK(&work->work, phy_chan_notify);
7307+ work->dev = dev;
7308+ queue_work(priv->hw->dev_workqueue, &work->work);
7309+ }
7310+}
7311+
7312+u8 mac802154_dev_get_dsn(const struct net_device *dev)
7313+{
7314+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7315+ u16 ret;
7316+
7317+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7318+
7319+ spin_lock_bh(&priv->mib_lock);
7320+ ret = priv->dsn++;
7321+ spin_unlock_bh(&priv->mib_lock);
7322+
7323+ return ret;
7324+}
7325+
7326+u8 mac802154_dev_get_bsn(const struct net_device *dev)
7327+{
7328+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7329+ u16 ret;
7330+
7331+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7332+
7333+ spin_lock_bh(&priv->mib_lock);
7334+ ret = priv->bsn++;
7335+ spin_unlock_bh(&priv->mib_lock);
7336+
7337+ return ret;
7338+}
7339+
7340+struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev)
7341+{
7342+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7343+ BUG_ON(dev->type != ARPHRD_IEEE802154);
7344+
7345+ return priv->hw;
7346+}
7347+
7348+struct wpan_phy *mac802154_get_phy(const struct net_device *dev)
7349+{
7350+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
7351+ BUG_ON(dev->type != ARPHRD_IEEE802154
7352+ && dev->type != ARPHRD_IEEE802154_MONITOR
7353+ && dev->type != ARPHRD_SMAC);
7354+
7355+ return to_phy(get_device(&priv->hw->phy->dev));
7356+}
7357diff --git a/net/mac802154/mib.h b/net/mac802154/mib.h
7358new file mode 100644
7359index 0000000..228f6d0
7360--- /dev/null
7361@@ -0,0 +1,35 @@
7362+/*
7363+ * Copyright 2008 Siemens AG
7364+ *
7365+ * This program is free software; you can redistribute it and/or modify
7366+ * it under the terms of the GNU General Public License version 2
7367+ * as published by the Free Software Foundation.
7368+ *
7369+ * This program is distributed in the hope that it will be useful,
7370+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7371+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7372+ * GNU General Public License for more details.
7373+ *
7374+ * You should have received a copy of the GNU General Public License along
7375+ * with this program; if not, write to the Free Software Foundation, Inc.,
7376+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7377+ *
7378+ */
7379+
7380+#ifndef MIB802154_H
7381+#define MIB802154_H
7382+
7383+/* FIXME: should be dropped in favour of generic MIB API */
7384+u8 mac802154_dev_get_dsn(const struct net_device *dev);
7385+u8 mac802154_dev_get_bsn(const struct net_device *dev);
7386+u16 mac802154_dev_get_pan_id(const struct net_device *dev);
7387+u16 mac802154_dev_get_short_addr(const struct net_device *dev);
7388+void mac802154_dev_set_pan_id(struct net_device *dev, u16 val);
7389+void mac802154_dev_set_pan_coord(struct net_device *dev);
7390+void mac802154_dev_set_short_addr(struct net_device *dev, u16 val);
7391+void mac802154_dev_set_ieee_addr(struct net_device *dev);
7392+void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
7393+struct wpan_phy *mac802154_get_phy(const struct net_device *dev);
7394+
7395+
7396+#endif
7397diff --git a/net/mac802154/monitor.c b/net/mac802154/monitor.c
7398new file mode 100644
7399index 0000000..24a4fbb
7400--- /dev/null
7401@@ -0,0 +1,117 @@
7402+/*
7403+ * Copyright 2007, 2008, 2009 Siemens AG
7404+ *
7405+ * This program is free software; you can redistribute it and/or modify
7406+ * it under the terms of the GNU General Public License version 2
7407+ * as published by the Free Software Foundation.
7408+ *
7409+ * This program is distributed in the hope that it will be useful,
7410+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7411+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7412+ * GNU General Public License for more details.
7413+ *
7414+ * You should have received a copy of the GNU General Public License along
7415+ * with this program; if not, write to the Free Software Foundation, Inc.,
7416+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7417+ *
7418+ * Written by:
7419+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
7420+ * Sergey Lapin <slapin@ossfans.org>
7421+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
7422+ */
7423+
7424+#include <linux/netdevice.h>
7425+#include <linux/skbuff.h>
7426+#include <linux/if_arp.h>
7427+#include <linux/nl802154.h>
7428+#include <linux/crc-ccitt.h>
7429+
7430+#include <net/mac802154.h>
7431+#include <net/wpan-phy.h>
7432+#include <linux/hardirq.h>
7433+
7434+#include "mac802154.h"
7435+
7436+static netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb, struct net_device *dev)
7437+{
7438+ struct mac802154_sub_if_data *priv;
7439+ u8 chan, page;
7440+
7441+ priv = netdev_priv(dev);
7442+
7443+ /* FIXME: locking */
7444+ chan = priv->hw->phy->current_channel;
7445+ page = priv->hw->phy->current_page;
7446+
7447+ if (chan == (u8)-1) /* not init */
7448+ return NETDEV_TX_OK;
7449+
7450+ BUG_ON(page >= WPAN_NUM_PAGES);
7451+ BUG_ON(chan >= 27);
7452+
7453+ skb->skb_iif = dev->ifindex;
7454+ dev->stats.tx_packets++;
7455+ dev->stats.tx_bytes += skb->len;
7456+
7457+ return mac802154_tx(priv->hw, skb, page, chan);
7458+}
7459+
7460+
7461+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb)
7462+{
7463+ struct sk_buff *skb2;
7464+ struct mac802154_sub_if_data *sdata;
7465+ u16 crc = crc_ccitt(0, skb->data, skb->len);
7466+ u8 *data;
7467+
7468+ rcu_read_lock();
7469+ list_for_each_entry_rcu(sdata, &priv->slaves, list) {
7470+ if (sdata->type != IEEE802154_DEV_MONITOR)
7471+ continue;
7472+
7473+ skb2 = skb_clone(skb, GFP_ATOMIC);
7474+ skb2->dev = sdata->dev;
7475+ skb2->pkt_type = PACKET_HOST;
7476+ data = skb_put(skb2, 2);
7477+ data[0] = crc & 0xff;
7478+ data[1] = crc >> 8;
7479+
7480+ if (in_interrupt())
7481+ netif_rx(skb2);
7482+ else
7483+ netif_rx_ni(skb2);
7484+ }
7485+ rcu_read_unlock();
7486+}
7487+
7488+static const struct net_device_ops mac802154_monitor_ops = {
7489+ .ndo_open = mac802154_slave_open,
7490+ .ndo_stop = mac802154_slave_close,
7491+ .ndo_start_xmit = mac802154_monitor_xmit,
7492+};
7493+
7494+void mac802154_monitor_setup(struct net_device *dev)
7495+{
7496+ struct mac802154_sub_if_data *priv;
7497+
7498+ dev->addr_len = 0;
7499+ dev->features = NETIF_F_HW_CSUM;
7500+ dev->hard_header_len = 0;
7501+ dev->needed_tailroom = 2; /* FCS */
7502+ dev->mtu = 127;
7503+ dev->tx_queue_len = 10;
7504+ dev->type = ARPHRD_IEEE802154_MONITOR;
7505+ dev->flags = IFF_NOARP | IFF_BROADCAST;
7506+ dev->watchdog_timeo = 0;
7507+
7508+ dev->destructor = free_netdev;
7509+ dev->netdev_ops = &mac802154_monitor_ops;
7510+ dev->ml_priv = &mac802154_mlme_simple;
7511+
7512+ priv = netdev_priv(dev);
7513+ priv->type = IEEE802154_DEV_MONITOR;
7514+
7515+ priv->chan = -1; /* not initialized */
7516+ priv->page = 0; /* for compat */
7517+}
7518+
7519diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
7520new file mode 100644
7521index 0000000..0e9d5d4
7522--- /dev/null
7523@@ -0,0 +1,117 @@
7524+/*
7525+ * Copyright (C) 2007, 2008, 2009 Siemens AG
7526+ *
7527+ * This program is free software; you can redistribute it and/or modify
7528+ * it under the terms of the GNU General Public License version 2
7529+ * as published by the Free Software Foundation.
7530+ *
7531+ * This program is distributed in the hope that it will be useful,
7532+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7533+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7534+ * GNU General Public License for more details.
7535+ *
7536+ * You should have received a copy of the GNU General Public License along
7537+ * with this program; if not, write to the Free Software Foundation, Inc.,
7538+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7539+ *
7540+ * Written by:
7541+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
7542+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
7543+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
7544+ */
7545+
7546+#include <linux/kernel.h>
7547+#include <linux/module.h>
7548+#include <linux/workqueue.h>
7549+#include <linux/netdevice.h>
7550+#include <linux/crc-ccitt.h>
7551+
7552+#include <net/mac802154.h>
7553+#include <net/ieee802154_netdev.h>
7554+
7555+#include "mac802154.h"
7556+
7557+static void mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb)
7558+{
7559+ struct mac802154_priv *priv = mac802154_to_priv(hw);
7560+
7561+ BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb));
7562+ pr_debug("%s()\n", __func__);
7563+
7564+ if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
7565+ u16 crc;
7566+
7567+ if (skb->len < 2) {
7568+ pr_debug("%s(): Got invalid frame\n", __func__);
7569+ goto out;
7570+ }
7571+ crc = crc_ccitt(0, skb->data, skb->len);
7572+ if (crc) {
7573+ pr_debug("%s(): CRC mismatch\n", __func__);
7574+ goto out;
7575+ }
7576+ skb_trim(skb, skb->len - 2); /* CRC */
7577+ }
7578+
7579+ mac802154_monitors_rx(priv, skb);
7580+ mac802154_smacs_rx(priv, skb);
7581+ mac802154_wpans_rx(priv, skb);
7582+
7583+out:
7584+ dev_kfree_skb(skb);
7585+ return;
7586+}
7587+
7588+static void __mac802154_rx_prepare(struct ieee802154_dev *dev,
7589+ struct sk_buff *skb, u8 lqi)
7590+{
7591+ BUG_ON(!skb);
7592+
7593+ mac_cb(skb)->lqi = lqi;
7594+
7595+ skb->protocol = htons(ETH_P_IEEE802154);
7596+
7597+ skb_reset_mac_header(skb);
7598+}
7599+
7600+void mac802154_rx(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi)
7601+{
7602+ __mac802154_rx_prepare(dev, skb, lqi);
7603+
7604+ mac802154_subif_rx(dev, skb);
7605+}
7606+EXPORT_SYMBOL(mac802154_rx);
7607+
7608+struct rx_work {
7609+ struct sk_buff *skb;
7610+ struct work_struct work;
7611+ struct ieee802154_dev *dev;
7612+};
7613+
7614+static void mac802154_rx_worker(struct work_struct *work)
7615+{
7616+ struct rx_work *rw = container_of(work, struct rx_work, work);
7617+ struct sk_buff *skb = rw->skb;
7618+
7619+ mac802154_subif_rx(rw->dev, skb);
7620+ kfree(rw);
7621+}
7622+
7623+void ieee802154_rx_irqsafe(struct ieee802154_dev *dev,
7624+ struct sk_buff *skb, u8 lqi)
7625+{
7626+ struct mac802154_priv *priv = mac802154_to_priv(dev);
7627+ struct rx_work *work = kzalloc(sizeof(struct rx_work), GFP_ATOMIC);
7628+
7629+ if (!work)
7630+ return;
7631+
7632+ __mac802154_rx_prepare(dev, skb, lqi);
7633+
7634+ INIT_WORK(&work->work, mac802154_rx_worker);
7635+ work->skb = skb;
7636+ work->dev = dev;
7637+
7638+ queue_work(priv->dev_workqueue, &work->work);
7639+}
7640+EXPORT_SYMBOL(ieee802154_rx_irqsafe);
7641diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
7642new file mode 100644
7643index 0000000..7c6f313
7644--- /dev/null
7645@@ -0,0 +1,203 @@
7646+/*
7647+ * scan.c
7648+ *
7649+ * Description: MAC scan helper functions.
7650+ *
7651+ * Copyright (C) 2007, 2008 Siemens AG
7652+ *
7653+ * This program is free software; you can redistribute it and/or modify
7654+ * it under the terms of the GNU General Public License version 2
7655+ * as published by the Free Software Foundation.
7656+ *
7657+ * This program is distributed in the hope that it will be useful,
7658+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7659+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7660+ * GNU General Public License for more details.
7661+ *
7662+ * You should have received a copy of the GNU General Public License along
7663+ * with this program; if not, write to the Free Software Foundation, Inc.,
7664+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7665+ *
7666+ * Written by:
7667+ * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
7668+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
7669+ */
7670+#include <linux/net.h>
7671+#include <linux/module.h>
7672+#include <linux/sched.h>
7673+#include <linux/netdevice.h>
7674+
7675+#include <net/mac802154.h>
7676+#include <net/nl802154.h>
7677+#include <net/ieee802154.h>
7678+#include <net/ieee802154_netdev.h>
7679+#include <net/wpan-phy.h>
7680+
7681+#include "mac802154.h"
7682+
7683+/*
7684+ * ED scan is periodic issuing of ed device function
7685+ * on evry permitted channel, so it is virtually PHY-only scan */
7686+
7687+struct scan_work {
7688+ struct work_struct work;
7689+
7690+ int (*scan_ch)(struct scan_work *work, int channel, u8 duration);
7691+ struct net_device *dev;
7692+
7693+ u8 edl[27];
7694+
7695+ u8 type;
7696+ u32 channels;
7697+ u8 page;
7698+ u8 duration;
7699+};
7700+
7701+static int scan_ed(struct scan_work *work, int channel, u8 duration)
7702+{
7703+ int ret;
7704+ struct mac802154_priv *hw = mac802154_slave_get_priv(work->dev);
7705+ pr_debug("ed scan channel %d duration %d\n", channel, duration);
7706+ mutex_lock(&hw->phy->pib_lock);
7707+ ret = hw->ops->ed(&hw->hw, &work->edl[channel]);
7708+ mutex_unlock(&hw->phy->pib_lock);
7709+ pr_debug("ed scan channel %d value %d\n", channel, work->edl[channel]);
7710+ return ret;
7711+}
7712+
7713+static int scan_passive(struct scan_work *work, int channel, u8 duration)
7714+{
7715+ unsigned long j;
7716+ pr_debug("passive scan channel %d duration %d\n", channel, duration);
7717+
7718+ /* Hope 2 msecs will be enough for scan */
7719+ j = msecs_to_jiffies(2);
7720+ while (j > 0)
7721+ j = schedule_timeout(j);
7722+
7723+ return 0;
7724+}
7725+
7726+/* Active scan is periodic submission of beacon request
7727+ * and waiting for beacons which is useful for collecting LWPAN information */
7728+static int scan_active(struct scan_work *work, int channel, u8 duration)
7729+{
7730+ int ret;
7731+ pr_debug("active scan channel %d duration %d\n", channel, duration);
7732+ ret = mac802154_send_beacon_req(work->dev);
7733+ if (ret)
7734+ return ret;
7735+ return scan_passive(work, channel, duration);
7736+}
7737+
7738+static int scan_orphan(struct scan_work *work, int channel, u8 duration)
7739+{
7740+ pr_debug("orphan scan channel %d duration %d\n", channel, duration);
7741+ return 0;
7742+}
7743+
7744+static void scanner(struct work_struct *work)
7745+{
7746+ struct scan_work *sw = container_of(work, struct scan_work, work);
7747+ struct mac802154_priv *hw = mac802154_slave_get_priv(sw->dev);
7748+ struct mac802154_sub_if_data *priv = netdev_priv(sw->dev);
7749+ int i;
7750+ int ret;
7751+
7752+ for (i = 0; i < 27; i++) {
7753+ if (!(sw->channels & (1 << i)))
7754+ continue;
7755+
7756+ mutex_lock(&hw->phy->pib_lock);
7757+ ret = hw->ops->set_channel(&hw->hw, sw->page, i);
7758+ mutex_unlock(&hw->phy->pib_lock);
7759+ if (ret)
7760+ goto exit_error;
7761+
7762+ priv->chan = i;
7763+ priv->page = sw->page;
7764+
7765+ ret = sw->scan_ch(sw, i, sw->duration);
7766+ if (ret)
7767+ goto exit_error;
7768+
7769+ sw->channels &= ~(1 << i);
7770+ }
7771+
7772+ ieee802154_nl_scan_confirm(sw->dev, IEEE802154_SUCCESS, sw->type,
7773+ sw->channels, sw->page, sw->edl/*, NULL */);
7774+
7775+ kfree(sw);
7776+
7777+ return;
7778+
7779+exit_error:
7780+ ieee802154_nl_scan_confirm(sw->dev, IEEE802154_INVALID_PARAMETER,
7781+ sw->type, sw->channels, sw->page, NULL/*, NULL */);
7782+ kfree(sw);
7783+ return;
7784+}
7785+
7786+/*
7787+ * Alloc ed_detect list for ED scan.
7788+ *
7789+ * @param mac current mac pointer
7790+ * @param type type of the scan to be performed
7791+ * @param channels 32-bit mask of requested to scan channels
7792+ * @param duration scan duration, see ieee802.15.4-2003.pdf, page 145.
7793+ * @return 0 if request is ok, errno otherwise.
7794+ */
7795+int mac802154_mlme_scan_req(struct net_device *dev,
7796+ u8 type, u32 channels, u8 page, u8 duration)
7797+{
7798+ struct mac802154_priv *hw = mac802154_slave_get_priv(dev);
7799+ struct scan_work *work;
7800+
7801+ pr_debug("%s()\n", __func__);
7802+
7803+ if (page > WPAN_NUM_PAGES)
7804+ goto inval;
7805+ if (duration > 14)
7806+ goto inval;
7807+ if (channels & ~hw->phy->channels_supported[page])
7808+ goto inval;
7809+
7810+ work = kzalloc(sizeof(struct scan_work), GFP_KERNEL);
7811+ if (!work)
7812+ goto inval;
7813+
7814+ work->dev = dev;
7815+ work->channels = channels;
7816+ work->page = page;
7817+ work->duration = duration;
7818+ work->type = type;
7819+
7820+ switch (type) {
7821+ case IEEE802154_MAC_SCAN_ED:
7822+ work->scan_ch = scan_ed;
7823+ break;
7824+ case IEEE802154_MAC_SCAN_ACTIVE:
7825+ work->scan_ch = scan_active;
7826+ break;
7827+ case IEEE802154_MAC_SCAN_PASSIVE:
7828+ work->scan_ch = scan_passive;
7829+ break;
7830+ case IEEE802154_MAC_SCAN_ORPHAN:
7831+ work->scan_ch = scan_orphan;
7832+ break;
7833+ default:
7834+ pr_debug("%s(): invalid type %d\n", __func__, type);
7835+ goto inval;
7836+ }
7837+
7838+ INIT_WORK(&work->work, scanner);
7839+ queue_work(hw->dev_workqueue, &work->work);
7840+
7841+ return 0;
7842+
7843+inval:
7844+ ieee802154_nl_scan_confirm(dev, IEEE802154_INVALID_PARAMETER, type,
7845+ channels, page, NULL/*, NULL */);
7846+ return -EINVAL;
7847+}
7848+
7849diff --git a/net/mac802154/smac.c b/net/mac802154/smac.c
7850new file mode 100644
7851index 0000000..88bf1e1
7852--- /dev/null
7853@@ -0,0 +1,128 @@
7854+/*
7855+ * Copyright 2010 Siemens AG
7856+ *
7857+ * This program is free software; you can redistribute it and/or modify
7858+ * it under the terms of the GNU General Public License version 2
7859+ * as published by the Free Software Foundation.
7860+ *
7861+ * This program is distributed in the hope that it will be useful,
7862+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7863+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7864+ * GNU General Public License for more details.
7865+ *
7866+ * You should have received a copy of the GNU General Public License along
7867+ * with this program; if not, write to the Free Software Foundation, Inc.,
7868+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
7869+ *
7870+ * Written by:
7871+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
7872+ */
7873+
7874+#include <linux/netdevice.h>
7875+#include <linux/skbuff.h>
7876+#include <linux/if_arp.h>
7877+#include <linux/nl802154.h>
7878+#include <linux/hardirq.h>
7879+
7880+#include <net/mac802154.h>
7881+#include <net/wpan-phy.h>
7882+
7883+#include "mac802154.h"
7884+
7885+static const u8 smac_header[] = {0x7E, 0xFF};
7886+
7887+static netdev_tx_t mac802154_smac_xmit(struct sk_buff *skb, struct net_device *dev)
7888+{
7889+ struct mac802154_sub_if_data *priv;
7890+ u8 chan, page;
7891+
7892+ priv = netdev_priv(dev);
7893+
7894+ /* FIXME: locking */
7895+ chan = priv->hw->phy->current_channel;
7896+ page = priv->hw->phy->current_page;
7897+
7898+ if (chan == (u8)-1) /* not init */
7899+ return NETDEV_TX_OK;
7900+
7901+ BUG_ON(page >= WPAN_NUM_PAGES);
7902+ BUG_ON(chan >= 27);
7903+
7904+ memcpy(skb_push(skb, sizeof(smac_header)), smac_header, sizeof(smac_header));
7905+
7906+ skb->skb_iif = dev->ifindex;
7907+ dev->stats.tx_packets++;
7908+ dev->stats.tx_bytes += skb->len;
7909+
7910+ return mac802154_tx(priv->hw, skb, page, chan);
7911+}
7912+
7913+void mac802154_smacs_rx(struct mac802154_priv *priv, struct sk_buff *skb)
7914+{
7915+ struct mac802154_sub_if_data *sdata;
7916+
7917+ if (skb->len < sizeof(smac_header))
7918+ return;
7919+
7920+ if (memcmp(skb->data, smac_header, sizeof(smac_header)))
7921+ return;
7922+
7923+ /*
7924+ * Currently we are the owner of the skb.
7925+ * We can change it's data pointers, provided we change them
7926+ * back at the end.
7927+ */
7928+
7929+ skb_pull(skb, sizeof(smac_header));
7930+
7931+ list_for_each_entry_rcu(sdata, &priv->slaves, list) {
7932+ struct sk_buff *skb2;
7933+
7934+ if (sdata->type != IEEE802154_DEV_SMAC)
7935+ continue;
7936+
7937+ skb2 = skb_clone(skb, GFP_ATOMIC);
7938+ skb2->dev = sdata->dev;
7939+ skb2->pkt_type = PACKET_HOST;
7940+
7941+ if (in_interrupt())
7942+ netif_rx(skb2);
7943+ else
7944+ netif_rx_ni(skb2);
7945+ }
7946+ rcu_read_unlock();
7947+
7948+ skb_push(skb, sizeof(smac_header));
7949+}
7950+
7951+static const struct net_device_ops mac802154_smac_ops = {
7952+ .ndo_open = mac802154_slave_open,
7953+ .ndo_stop = mac802154_slave_close,
7954+ .ndo_start_xmit = mac802154_smac_xmit,
7955+};
7956+
7957+void mac802154_smac_setup(struct net_device *dev)
7958+{
7959+ struct mac802154_sub_if_data *priv;
7960+
7961+ dev->addr_len = 0;
7962+ dev->features = NETIF_F_HW_CSUM;
7963+ dev->hard_header_len = 2;
7964+ dev->needed_tailroom = 2; /* FCS */
7965+ dev->mtu = 123; /* 127 - 2 (FCS) - 2 (header) */
7966+ dev->tx_queue_len = 10;
7967+ dev->type = ARPHRD_SMAC;
7968+ dev->flags = IFF_NOARP | IFF_BROADCAST;
7969+ dev->watchdog_timeo = 0;
7970+
7971+ dev->destructor = free_netdev;
7972+ dev->netdev_ops = &mac802154_smac_ops;
7973+ dev->ml_priv = &mac802154_mlme_simple;
7974+
7975+ priv = netdev_priv(dev);
7976+ priv->type = IEEE802154_DEV_SMAC;
7977+
7978+ priv->chan = -1; /* not initialized */
7979+ priv->page = 0; /* for compat */
7980+}
7981+
7982diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
7983new file mode 100644
7984index 0000000..0703195
7985--- /dev/null
7986@@ -0,0 +1,106 @@
7987+/*
7988+ * Copyright 2007, 2008, 2009 Siemens AG
7989+ *
7990+ * This program is free software; you can redistribute it and/or modify
7991+ * it under the terms of the GNU General Public License version 2
7992+ * as published by the Free Software Foundation.
7993+ *
7994+ * This program is distributed in the hope that it will be useful,
7995+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7996+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7997+ * GNU General Public License for more details.
7998+ *
7999+ * You should have received a copy of the GNU General Public License along
8000+ * with this program; if not, write to the Free Software Foundation, Inc.,
8001+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8002+ *
8003+ * Written by:
8004+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
8005+ * Sergey Lapin <slapin@ossfans.org>
8006+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8007+ */
8008+
8009+#include <linux/netdevice.h>
8010+#include <linux/if_arp.h>
8011+#include <linux/crc-ccitt.h>
8012+
8013+#include <net/mac802154.h>
8014+#include <net/wpan-phy.h>
8015+
8016+#include "mac802154.h"
8017+
8018+struct xmit_work {
8019+ struct sk_buff *skb;
8020+ struct work_struct work;
8021+ struct mac802154_priv *priv;
8022+ u8 page;
8023+ u8 chan;
8024+};
8025+
8026+static void mac802154_xmit_worker(struct work_struct *work)
8027+{
8028+ struct xmit_work *xw = container_of(work, struct xmit_work, work);
8029+ int res;
8030+
8031+ BUG_ON(xw->chan == (u8)-1);
8032+
8033+ mutex_lock(&xw->priv->phy->pib_lock);
8034+ if (xw->priv->phy->current_channel != xw->chan ||
8035+ xw->priv->phy->current_page != xw->page) {
8036+ res = xw->priv->ops->set_channel(&xw->priv->hw,
8037+ xw->page,
8038+ xw->chan);
8039+ if (res) {
8040+ pr_debug("set_channel failed\n");
8041+ goto out;
8042+ }
8043+ }
8044+
8045+ res = xw->priv->ops->xmit(&xw->priv->hw, xw->skb);
8046+
8047+out:
8048+ mutex_unlock(&xw->priv->phy->pib_lock);
8049+
8050+ /* FIXME: result processing and/or requeue!!! */
8051+ dev_kfree_skb(xw->skb);
8052+
8053+ kfree(xw);
8054+}
8055+
8056+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
8057+ u8 page, u8 chan)
8058+{
8059+ struct xmit_work *work;
8060+
8061+ if (WARN_ON(!(priv->phy->channels_supported[page] &
8062+ (1 << chan))))
8063+ return NETDEV_TX_OK;
8064+
8065+ mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
8066+
8067+ if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
8068+ u16 crc = crc_ccitt(0, skb->data, skb->len);
8069+ u8 *data = skb_put(skb, 2);
8070+ data[0] = crc & 0xff;
8071+ data[1] = crc >> 8;
8072+ }
8073+
8074+ if (skb_cow_head(skb, priv->hw.extra_tx_headroom)) {
8075+ dev_kfree_skb(skb);
8076+ return NETDEV_TX_OK;
8077+ }
8078+
8079+ work = kzalloc(sizeof(struct xmit_work), GFP_ATOMIC);
8080+ if (!work)
8081+ return NETDEV_TX_BUSY;
8082+
8083+ INIT_WORK(&work->work, mac802154_xmit_worker);
8084+ work->skb = skb;
8085+ work->priv = priv;
8086+ work->page = page;
8087+ work->chan = chan;
8088+
8089+ queue_work(priv->dev_workqueue, &work->work);
8090+
8091+ return NETDEV_TX_OK;
8092+}
8093diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
8094new file mode 100644
8095index 0000000..d5369a8
8096--- /dev/null
8097@@ -0,0 +1,631 @@
8098+/*
8099+ * Copyright 2007, 2008, 2009 Siemens AG
8100+ *
8101+ * This program is free software; you can redistribute it and/or modify
8102+ * it under the terms of the GNU General Public License version 2
8103+ * as published by the Free Software Foundation.
8104+ *
8105+ * This program is distributed in the hope that it will be useful,
8106+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8107+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8108+ * GNU General Public License for more details.
8109+ *
8110+ * You should have received a copy of the GNU General Public License along
8111+ * with this program; if not, write to the Free Software Foundation, Inc.,
8112+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8113+ *
8114+ * Written by:
8115+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
8116+ * Sergey Lapin <slapin@ossfans.org>
8117+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8118+ */
8119+
8120+#include <linux/netdevice.h>
8121+#include <linux/capability.h>
8122+#include <linux/module.h>
8123+#include <linux/if_arp.h>
8124+#include <linux/rculist.h>
8125+#include <linux/random.h>
8126+#include <linux/crc-ccitt.h>
8127+#include <linux/nl802154.h>
8128+#include <linux/hardirq.h>
8129+
8130+#include <net/rtnetlink.h>
8131+#include <net/af_ieee802154.h>
8132+#include <net/mac802154.h>
8133+#include <net/ieee802154_netdev.h>
8134+#include <net/ieee802154.h>
8135+#include <net/wpan-phy.h>
8136+
8137+#include "mac802154.h"
8138+#include "mib.h"
8139+
8140+static netdev_tx_t mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
8141+{
8142+ struct mac802154_sub_if_data *priv;
8143+ u8 chan, page;
8144+
8145+ priv = netdev_priv(dev);
8146+
8147+ spin_lock_bh(&priv->mib_lock);
8148+ chan = priv->chan;
8149+ page = priv->page;
8150+ spin_unlock_bh(&priv->mib_lock);
8151+
8152+ if (chan == (u8)-1) /* not init */
8153+ return NETDEV_TX_OK;
8154+
8155+ BUG_ON(page >= WPAN_NUM_PAGES);
8156+ BUG_ON(chan >= 27);
8157+
8158+ skb->skb_iif = dev->ifindex;
8159+ dev->stats.tx_packets++;
8160+ dev->stats.tx_bytes += skb->len;
8161+
8162+ return mac802154_tx(priv->hw, skb, page, chan);
8163+}
8164+
8165+static int mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr,
8166+ int cmd)
8167+{
8168+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
8169+ struct sockaddr_ieee802154 *sa =
8170+ (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
8171+ int err = -ENOIOCTLCMD;
8172+
8173+ spin_lock_bh(&priv->mib_lock);
8174+
8175+ switch (cmd) {
8176+ case SIOCGIFADDR:
8177+ if (priv->pan_id == IEEE802154_PANID_BROADCAST ||
8178+ priv->short_addr == IEEE802154_ADDR_BROADCAST) {
8179+ err = -EADDRNOTAVAIL;
8180+ break;
8181+ }
8182+
8183+ sa->family = AF_IEEE802154;
8184+ sa->addr.addr_type = IEEE802154_ADDR_SHORT;
8185+ sa->addr.pan_id = priv->pan_id;
8186+ sa->addr.short_addr = priv->short_addr;
8187+
8188+ err = 0;
8189+ break;
8190+ case SIOCSIFADDR:
8191+ dev_warn(&dev->dev,
8192+ "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n");
8193+ if (sa->family != AF_IEEE802154 ||
8194+ sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
8195+ sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
8196+ sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
8197+ sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
8198+ err = -EINVAL;
8199+ break;
8200+ }
8201+
8202+ priv->pan_id = sa->addr.pan_id;
8203+ priv->short_addr = sa->addr.short_addr;
8204+ err = 0;
8205+ break;
8206+ }
8207+ spin_unlock_bh(&priv->mib_lock);
8208+ return err;
8209+}
8210+
8211+static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
8212+{
8213+ struct sockaddr *addr = p;
8214+
8215+ if (netif_running(dev))
8216+ return -EBUSY;
8217+ /* FIXME: validate addr */
8218+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
8219+ mac802154_dev_set_ieee_addr(dev);
8220+ return 0;
8221+}
8222+
8223+static void mac802154_haddr_copy_swap(u8 *dest, const u8 *src)
8224+{
8225+ int i;
8226+ for (i = 0; i < IEEE802154_ADDR_LEN; i++)
8227+ dest[IEEE802154_ADDR_LEN - i - 1] = src[i];
8228+}
8229+
8230+static int mac802154_header_create(struct sk_buff *skb,
8231+ struct net_device *dev,
8232+ unsigned short type, const void *_daddr,
8233+ const void *_saddr, unsigned len)
8234+{
8235+ u8 head[24] = {};
8236+ int pos = 0;
8237+
8238+ u16 fc;
8239+ const struct ieee802154_addr *saddr = _saddr;
8240+ const struct ieee802154_addr *daddr = _daddr;
8241+ struct ieee802154_addr dev_addr;
8242+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
8243+
8244+ fc = mac_cb_type(skb);
8245+ if (mac_cb_is_ackreq(skb))
8246+ fc |= IEEE802154_FC_ACK_REQ;
8247+
8248+ pos = 2;
8249+
8250+ head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
8251+
8252+ if (!daddr)
8253+ return -EINVAL;
8254+
8255+ if (!saddr) {
8256+ spin_lock_bh(&priv->mib_lock);
8257+ if (priv->short_addr == IEEE802154_ADDR_BROADCAST ||
8258+ priv->short_addr == IEEE802154_ADDR_UNDEF ||
8259+ priv->pan_id == IEEE802154_PANID_BROADCAST) {
8260+ dev_addr.addr_type = IEEE802154_ADDR_LONG;
8261+ memcpy(dev_addr.hwaddr, dev->dev_addr,
8262+ IEEE802154_ADDR_LEN);
8263+ } else {
8264+ dev_addr.addr_type = IEEE802154_ADDR_SHORT;
8265+ dev_addr.short_addr = priv->short_addr;
8266+ }
8267+
8268+ dev_addr.pan_id = priv->pan_id;
8269+ saddr = &dev_addr;
8270+
8271+ spin_unlock_bh(&priv->mib_lock);
8272+ }
8273+
8274+ if (daddr->addr_type != IEEE802154_ADDR_NONE) {
8275+ fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
8276+
8277+ head[pos++] = daddr->pan_id & 0xff;
8278+ head[pos++] = daddr->pan_id >> 8;
8279+
8280+ if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
8281+ head[pos++] = daddr->short_addr & 0xff;
8282+ head[pos++] = daddr->short_addr >> 8;
8283+ } else {
8284+ mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
8285+ pos += IEEE802154_ADDR_LEN;
8286+ }
8287+ }
8288+
8289+ if (saddr->addr_type != IEEE802154_ADDR_NONE) {
8290+ fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
8291+
8292+ if ((saddr->pan_id == daddr->pan_id) &&
8293+ (saddr->pan_id != IEEE802154_PANID_BROADCAST))
8294+ /* PANID compression/ intra PAN */
8295+ fc |= IEEE802154_FC_INTRA_PAN;
8296+ else {
8297+ head[pos++] = saddr->pan_id & 0xff;
8298+ head[pos++] = saddr->pan_id >> 8;
8299+ }
8300+
8301+ if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
8302+ head[pos++] = saddr->short_addr & 0xff;
8303+ head[pos++] = saddr->short_addr >> 8;
8304+ } else {
8305+ mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
8306+ pos += IEEE802154_ADDR_LEN;
8307+ }
8308+ }
8309+
8310+ head[0] = fc;
8311+ head[1] = fc >> 8;
8312+
8313+ memcpy(skb_push(skb, pos), head, pos);
8314+
8315+ return pos;
8316+}
8317+
8318+static int mac802154_header_parse(const struct sk_buff *skb,
8319+ unsigned char *haddr)
8320+{
8321+ const u8 *hdr = skb_mac_header(skb), *tail = skb_tail_pointer(skb);
8322+ struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
8323+ u16 fc;
8324+ int da_type;
8325+
8326+ if (hdr + 3 > tail)
8327+ goto malformed;
8328+
8329+ fc = hdr[0] | (hdr[1] << 8);
8330+
8331+ hdr += 3;
8332+
8333+ da_type = IEEE802154_FC_DAMODE(fc);
8334+ addr->addr_type = IEEE802154_FC_SAMODE(fc);
8335+
8336+ switch (da_type) {
8337+ case IEEE802154_ADDR_NONE:
8338+ if (fc & IEEE802154_FC_INTRA_PAN)
8339+ goto malformed;
8340+ break;
8341+
8342+ case IEEE802154_ADDR_LONG:
8343+ if (hdr + 2 > tail)
8344+ goto malformed;
8345+ if (fc & IEEE802154_FC_INTRA_PAN) {
8346+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8347+ hdr += 2;
8348+ }
8349+
8350+ if (hdr + IEEE802154_ADDR_LEN > tail)
8351+ goto malformed;
8352+ hdr += IEEE802154_ADDR_LEN;
8353+ break;
8354+
8355+ case IEEE802154_ADDR_SHORT:
8356+ if (hdr + 2 > tail)
8357+ goto malformed;
8358+ if (fc & IEEE802154_FC_INTRA_PAN) {
8359+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8360+ hdr += 2;
8361+ }
8362+
8363+ if (hdr + 2 > tail)
8364+ goto malformed;
8365+ hdr += 2;
8366+ break;
8367+
8368+ default:
8369+ goto malformed;
8370+
8371+ }
8372+
8373+ switch (addr->addr_type) {
8374+ case IEEE802154_ADDR_NONE:
8375+ break;
8376+
8377+ case IEEE802154_ADDR_LONG:
8378+ if (hdr + 2 > tail)
8379+ goto malformed;
8380+ if (!(fc & IEEE802154_FC_INTRA_PAN)) {
8381+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8382+ hdr += 2;
8383+ }
8384+
8385+ if (hdr + IEEE802154_ADDR_LEN > tail)
8386+ goto malformed;
8387+ mac802154_haddr_copy_swap(addr->hwaddr, hdr);
8388+ hdr += IEEE802154_ADDR_LEN;
8389+ break;
8390+
8391+ case IEEE802154_ADDR_SHORT:
8392+ if (hdr + 2 > tail)
8393+ goto malformed;
8394+ if (!(fc & IEEE802154_FC_INTRA_PAN)) {
8395+ addr->pan_id = hdr[0] | (hdr[1] << 8);
8396+ hdr += 2;
8397+ }
8398+
8399+ if (hdr + 2 > tail)
8400+ goto malformed;
8401+ addr->short_addr = hdr[0] | (hdr[1] << 8);
8402+ hdr += 2;
8403+ break;
8404+
8405+ default:
8406+ goto malformed;
8407+
8408+ }
8409+
8410+ return sizeof(struct ieee802154_addr);
8411+
8412+malformed:
8413+ pr_debug("malformed packet\n");
8414+ return 0;
8415+}
8416+
8417+static struct header_ops mac802154_header_ops = {
8418+ .create = mac802154_header_create,
8419+ .parse = mac802154_header_parse,
8420+};
8421+
8422+static const struct net_device_ops mac802154_wpan_ops = {
8423+ .ndo_open = mac802154_slave_open,
8424+ .ndo_stop = mac802154_slave_close,
8425+ .ndo_start_xmit = mac802154_wpan_xmit,
8426+ .ndo_do_ioctl = mac802154_wpan_ioctl,
8427+ .ndo_set_mac_address = mac802154_wpan_mac_addr,
8428+};
8429+
8430+void mac802154_wpan_setup(struct net_device *dev)
8431+{
8432+ struct mac802154_sub_if_data *priv;
8433+
8434+ dev->addr_len = IEEE802154_ADDR_LEN;
8435+ memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
8436+ dev->features = NETIF_F_HW_CSUM;
8437+ dev->hard_header_len = 2 + 1 + 20 + 14;
8438+ dev->header_ops = &mac802154_header_ops;
8439+ dev->needed_tailroom = 2; /* FCS */
8440+ dev->mtu = 127;
8441+ dev->tx_queue_len = 10;
8442+ dev->type = ARPHRD_IEEE802154;
8443+ dev->flags = IFF_NOARP | IFF_BROADCAST;
8444+ dev->watchdog_timeo = 0;
8445+
8446+ dev->destructor = free_netdev;
8447+ dev->netdev_ops = &mac802154_wpan_ops;
8448+ dev->ml_priv = &mac802154_mlme_wpan.wpan_ops;
8449+
8450+ priv = netdev_priv(dev);
8451+ priv->type = IEEE802154_DEV_WPAN;
8452+
8453+ priv->chan = -1; /* not initialized */
8454+ priv->page = 0; /* for compat */
8455+
8456+ spin_lock_init(&priv->mib_lock);
8457+
8458+ get_random_bytes(&priv->bsn, 1);
8459+ get_random_bytes(&priv->dsn, 1);
8460+
8461+ priv->pan_id = IEEE802154_PANID_BROADCAST;
8462+ priv->short_addr = IEEE802154_ADDR_BROADCAST;
8463+}
8464+
8465+static int mac802154_process_ack(struct net_device *dev, struct sk_buff *skb)
8466+{
8467+ pr_debug("got ACK for SEQ=%d\n", mac_cb(skb)->seq);
8468+
8469+ kfree_skb(skb);
8470+ return NET_RX_SUCCESS;
8471+}
8472+
8473+static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
8474+{
8475+ if (in_interrupt())
8476+ return netif_rx(skb);
8477+ else
8478+ return netif_rx_ni(skb);
8479+}
8480+
8481+static int mac802154_subif_frame(struct mac802154_sub_if_data *sdata,
8482+ struct sk_buff *skb)
8483+{
8484+ pr_debug("%s Getting packet via slave interface %s\n",
8485+ __func__, sdata->dev->name);
8486+
8487+ spin_lock_bh(&sdata->mib_lock);
8488+
8489+ switch (mac_cb(skb)->da.addr_type) {
8490+ case IEEE802154_ADDR_NONE:
8491+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE)
8492+ /* FIXME: check if we are PAN coordinator :) */
8493+ skb->pkt_type = PACKET_OTHERHOST;
8494+ else
8495+ /* ACK comes with both addresses empty */
8496+ skb->pkt_type = PACKET_HOST;
8497+ break;
8498+ case IEEE802154_ADDR_LONG:
8499+ if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
8500+ mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
8501+ skb->pkt_type = PACKET_OTHERHOST;
8502+ else if (!memcmp(mac_cb(skb)->da.hwaddr, sdata->dev->dev_addr,
8503+ IEEE802154_ADDR_LEN))
8504+ skb->pkt_type = PACKET_HOST;
8505+ else
8506+ skb->pkt_type = PACKET_OTHERHOST;
8507+ break;
8508+ case IEEE802154_ADDR_SHORT:
8509+ if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
8510+ mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
8511+ skb->pkt_type = PACKET_OTHERHOST;
8512+ else if (mac_cb(skb)->da.short_addr == sdata->short_addr)
8513+ skb->pkt_type = PACKET_HOST;
8514+ else if (mac_cb(skb)->da.short_addr ==
8515+ IEEE802154_ADDR_BROADCAST)
8516+ skb->pkt_type = PACKET_BROADCAST;
8517+ else
8518+ skb->pkt_type = PACKET_OTHERHOST;
8519+ break;
8520+ }
8521+
8522+ spin_unlock_bh(&sdata->mib_lock);
8523+
8524+ skb->dev = sdata->dev;
8525+
8526+ if (skb->pkt_type == PACKET_HOST && mac_cb_is_ackreq(skb) &&
8527+ !(sdata->hw->hw.flags & IEEE802154_HW_AACK))
8528+ dev_warn(&sdata->dev->dev,
8529+ "ACK requested, however AACK not supported.\n");
8530+
8531+ switch (mac_cb_type(skb)) {
8532+ case IEEE802154_FC_TYPE_BEACON:
8533+ return mac802154_process_beacon(sdata->dev, skb);
8534+ case IEEE802154_FC_TYPE_ACK:
8535+ return mac802154_process_ack(sdata->dev, skb);
8536+ case IEEE802154_FC_TYPE_MAC_CMD:
8537+ return mac802154_process_cmd(sdata->dev, skb);
8538+ case IEEE802154_FC_TYPE_DATA:
8539+ return mac802154_process_data(sdata->dev, skb);
8540+ default:
8541+ pr_warning("ieee802154: Bad frame received (type = %d)\n",
8542+ mac_cb_type(skb));
8543+ kfree_skb(skb);
8544+ return NET_RX_DROP;
8545+ }
8546+}
8547+
8548+static u8 fetch_skb_u8(struct sk_buff *skb)
8549+{
8550+ u8 ret;
8551+
8552+ BUG_ON(skb->len < 1);
8553+
8554+ ret = skb->data[0];
8555+ skb_pull(skb, 1);
8556+
8557+ return ret;
8558+}
8559+
8560+static u16 fetch_skb_u16(struct sk_buff *skb)
8561+{
8562+ u16 ret;
8563+
8564+ BUG_ON(skb->len < 2);
8565+
8566+ ret = skb->data[0] + (skb->data[1] * 256);
8567+ skb_pull(skb, 2);
8568+ return ret;
8569+}
8570+
8571+static void fetch_skb_u64(struct sk_buff *skb, u8 *dest)
8572+{
8573+ int i;
8574+
8575+ BUG_ON(skb->len < IEEE802154_ADDR_LEN);
8576+
8577+ for (i = 0; i < IEEE802154_ADDR_LEN; i++)
8578+ dest[IEEE802154_ADDR_LEN - i - 1] = skb->data[i];
8579+ skb_pull(skb, IEEE802154_ADDR_LEN);
8580+}
8581+
8582+#define IEEE802154_FETCH_U8(skb, var) \
8583+ do { \
8584+ if (skb->len < 1) \
8585+ goto exit_error; \
8586+ var = fetch_skb_u8(skb); \
8587+ } while (0)
8588+
8589+#define IEEE802154_FETCH_U16(skb, var) \
8590+ do { \
8591+ if (skb->len < 2) \
8592+ goto exit_error; \
8593+ var = fetch_skb_u16(skb); \
8594+ } while (0)
8595+
8596+#define IEEE802154_FETCH_U64(skb, var) \
8597+ do { \
8598+ if (skb->len < IEEE802154_ADDR_LEN) \
8599+ goto exit_error; \
8600+ fetch_skb_u64(skb, var); \
8601+ } while (0)
8602+
8603+static int parse_frame_start(struct sk_buff *skb)
8604+{
8605+ u8 *head = skb->data;
8606+ u16 fc;
8607+
8608+ if (skb->len < 3) {
8609+ pr_debug("frame size %d bytes is too short\n", skb->len);
8610+ return -EINVAL;
8611+ }
8612+
8613+ IEEE802154_FETCH_U16(skb, fc);
8614+ IEEE802154_FETCH_U8(skb, mac_cb(skb)->seq);
8615+
8616+ pr_debug("%s: %04x dsn%02x\n", __func__, fc, head[2]);
8617+
8618+ mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc);
8619+
8620+ if (fc & IEEE802154_FC_ACK_REQ) {
8621+ pr_debug("%s(): ACKNOWLEDGE required\n", __func__);
8622+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
8623+ }
8624+
8625+ if (fc & IEEE802154_FC_SECEN)
8626+ mac_cb(skb)->flags |= MAC_CB_FLAG_SECEN;
8627+
8628+ if (fc & IEEE802154_FC_INTRA_PAN)
8629+ mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN;
8630+
8631+ /* TODO */
8632+ if (mac_cb_is_secen(skb)) {
8633+ pr_info("security support is not implemented\n");
8634+ return -EINVAL;
8635+ }
8636+
8637+ mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc);
8638+ if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_NONE)
8639+ pr_debug("%s(): src addr_type is NONE\n", __func__);
8640+
8641+ mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc);
8642+ if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_NONE)
8643+ pr_debug("%s(): dst addr_type is NONE\n", __func__);
8644+
8645+ if (IEEE802154_FC_TYPE(fc) == IEEE802154_FC_TYPE_ACK) {
8646+ /* ACK can only have NONE-type addresses */
8647+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE ||
8648+ mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE)
8649+ return -EINVAL;
8650+ }
8651+
8652+ if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) {
8653+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->da.pan_id);
8654+
8655+ if (mac_cb_is_intrapan(skb)) { /* ! panid compress */
8656+ pr_debug("%s(): src IEEE802154_FC_INTRA_PAN\n",
8657+ __func__);
8658+ mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id;
8659+ pr_debug("%s(): src PAN address %04x\n",
8660+ __func__, mac_cb(skb)->sa.pan_id);
8661+ }
8662+
8663+ pr_debug("%s(): dst PAN address %04x\n",
8664+ __func__, mac_cb(skb)->da.pan_id);
8665+
8666+ if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) {
8667+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->da.short_addr);
8668+ pr_debug("%s(): dst SHORT address %04x\n",
8669+ __func__, mac_cb(skb)->da.short_addr);
8670+
8671+ } else {
8672+ IEEE802154_FETCH_U64(skb, mac_cb(skb)->da.hwaddr);
8673+ pr_debug("%s(): dst hardware addr\n", __func__);
8674+ }
8675+ }
8676+
8677+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) {
8678+ pr_debug("%s(): got src non-NONE address\n", __func__);
8679+ if (!(mac_cb_is_intrapan(skb))) { /* ! panid compress */
8680+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->sa.pan_id);
8681+ pr_debug("%s(): src IEEE802154_FC_INTRA_PAN\n",
8682+ __func__);
8683+ }
8684+
8685+ if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) {
8686+ IEEE802154_FETCH_U16(skb, mac_cb(skb)->sa.short_addr);
8687+ pr_debug("%s(): src IEEE802154_ADDR_SHORT\n",
8688+ __func__);
8689+ } else {
8690+ IEEE802154_FETCH_U64(skb, mac_cb(skb)->sa.hwaddr);
8691+ pr_debug("%s(): src hardware addr\n", __func__);
8692+ }
8693+ }
8694+
8695+ return 0;
8696+
8697+exit_error:
8698+ return -EINVAL;
8699+}
8700+
8701+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
8702+{
8703+ int ret;
8704+ struct mac802154_sub_if_data *sdata;
8705+ struct sk_buff *skb2;
8706+
8707+ ret = parse_frame_start(skb); /* 3 bytes pulled after this */
8708+ if (ret) {
8709+ pr_debug("%s(): Got invalid frame\n", __func__);
8710+ return;
8711+ }
8712+
8713+ pr_debug("%s() frame %d\n", __func__, mac_cb_type(skb));
8714+
8715+ rcu_read_lock();
8716+ list_for_each_entry_rcu(sdata, &priv->slaves, list)
8717+ {
8718+ if (sdata->type != IEEE802154_DEV_WPAN)
8719+ continue;
8720+
8721+ skb2 = skb_clone(skb, GFP_ATOMIC);
8722+ if (skb2)
8723+ mac802154_subif_frame(sdata, skb2);
8724+ }
8725+
8726+ rcu_read_unlock();
8727+}
8728+
8729diff --git a/net/zigbee/Kconfig b/net/zigbee/Kconfig
8730new file mode 100644
8731index 0000000..85134a9
8732--- /dev/null
8733@@ -0,0 +1,7 @@
8734+config ZIGBEE
8735+ tristate "ZigBee Low-Rate Wireless Personal Area Networks support (EXPERIMENTAL)"
8736+ depends on EXPERIMENTAL && BROKEN
8737+ ---help---
8738+
8739+ Say Y here to compile ZigBee support into the kernel or say M to
8740+ compile it as modules.
8741diff --git a/net/zigbee/Makefile b/net/zigbee/Makefile
8742new file mode 100644
8743index 0000000..8c2eee5
8744--- /dev/null
8745@@ -0,0 +1,5 @@
8746+obj-$(CONFIG_ZIGBEE) += af_zb.o
8747+
8748+af_zb-objs := af_zigbee.o dgram.o
8749+
8750+EXTRA_CFLAGS += -Wall -DEXPORT_SYMTAB -DCONFIG_FFD -DCONFIG_ZIGBEE_DEBUG -DIEEE80215_DEBUG -DDEBUG
8751diff --git a/net/zigbee/af_zigbee.c b/net/zigbee/af_zigbee.c
8752new file mode 100644
8753index 0000000..820d668
8754--- /dev/null
8755@@ -0,0 +1,285 @@
8756+/*
8757+ * ZigBee socket interface
8758+ *
8759+ * Copyright 2008, 2009 Siemens AG
8760+ *
8761+ * This program is free software; you can redistribute it and/or modify
8762+ * it under the terms of the GNU General Public License version 2
8763+ * as published by the Free Software Foundation.
8764+ *
8765+ * This program is distributed in the hope that it will be useful,
8766+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8767+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8768+ * GNU General Public License for more details.
8769+ *
8770+ * You should have received a copy of the GNU General Public License along
8771+ * with this program; if not, write to the Free Software Foundation, Inc.,
8772+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
8773+ *
8774+ * Written by:
8775+ * Sergey Lapin <slapin@ossfans.org>
8776+ * Maxim Yu. Osipov <Maksim.Osipov@siemens.com>
8777+ */
8778+#include <linux/net.h>
8779+#include <linux/capability.h>
8780+#include <linux/module.h>
8781+#include <linux/if_arp.h>
8782+#include <linux/if.h>
8783+#include <linux/termios.h> /* For TIOCOUTQ/INQ */
8784+#include <linux/list.h>
8785+#include <net/datalink.h>
8786+#include <net/psnap.h>
8787+#include <net/sock.h>
8788+#include <net/tcp_states.h>
8789+#include <net/route.h>
8790+
8791+//#include <net/ieee80215/af_ieee80215.h>
8792+#include <net/zigbee/af_zigbee.h>
8793+#include <net/zigbee/nwk.h>
8794+
8795+#define DBG_DUMP(data, len) { \
8796+ int i; \
8797+ pr_debug("file %s: function: %s: data: len %d:\n", __FILE__, __func__, len); \
8798+ for (i = 0; i < len; i++) {\
8799+ pr_debug("%02x: %02x\n", i, (data)[i]); \
8800+ } \
8801+}
8802+
8803+static int zb_sock_release(struct socket *sock)
8804+{
8805+ struct sock *sk = sock->sk;
8806+
8807+ if (sk) {
8808+ sock->sk = NULL;
8809+ sk->sk_prot->close(sk, 0);
8810+ }
8811+ return 0;
8812+}
8813+static int zb_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
8814+{
8815+ struct sock *sk = sock->sk;
8816+
8817+ return sk->sk_prot->sendmsg(iocb, sk, msg, len);
8818+}
8819+
8820+static int zb_sock_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
8821+{
8822+ struct sock *sk = sock->sk;
8823+
8824+ if (sk->sk_prot->bind)
8825+ return sk->sk_prot->bind(sk, uaddr, addr_len);
8826+
8827+ return sock_no_bind(sock, uaddr, addr_len);
8828+}
8829+
8830+static int zb_sock_connect(struct socket *sock, struct sockaddr *uaddr,
8831+ int addr_len, int flags)
8832+{
8833+ struct sock *sk = sock->sk;
8834+
8835+ if (uaddr->sa_family == AF_UNSPEC)
8836+ return sk->sk_prot->disconnect(sk, flags);
8837+
8838+ return sk->sk_prot->connect(sk, uaddr, addr_len);
8839+}
8840+
8841+#if 0
8842+static int zb_dev_ioctl(struct sock *sk, struct ifreq __user *arg, unsigned int cmd)
8843+{
8844+ struct ifreq ifr;
8845+ int ret = -EINVAL;
8846+ struct net_device *dev;
8847+
8848+ if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
8849+ return -EFAULT;
8850+
8851+ ifr.ifr_name[IFNAMSIZ-1] = 0;
8852+
8853+ dev_load(sock_net(sk), ifr.ifr_name);
8854+ dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);
8855+ if (dev->type == ARPHRD_ZIGBEE || dev->type == ARPHRD_ZIGBEE_PHY)
8856+ ret = dev->do_ioctl(dev, &ifr, cmd);
8857+
8858+ if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
8859+ ret = -EFAULT;
8860+ dev_put(dev);
8861+
8862+ return ret;
8863+}
8864+#endif
8865+
8866+static int zb_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
8867+{
8868+ struct sock *sk = sock->sk;
8869+
8870+ switch (cmd) {
8871+ case SIOCGSTAMP:
8872+ return sock_get_timestamp(sk, (struct timeval __user *)arg);
8873+ case SIOCGSTAMPNS:
8874+ return sock_get_timestampns(sk, (struct timespec __user *)arg);
8875+#if 0
8876+ case SIOCGIFADDR:
8877+ case SIOCSIFADDR:
8878+ return zb_dev_ioctl(sk, (struct ifreq __user *)arg, cmd);
8879+#endif
8880+ default:
8881+ if (!sk->sk_prot->ioctl)
8882+ return -ENOIOCTLCMD;
8883+ return sk->sk_prot->ioctl(sk, cmd, arg);
8884+ }
8885+}
8886+
8887+static const struct proto_ops zb_dgram_ops = {
8888+ .family = PF_ZIGBEE,
8889+ .owner = THIS_MODULE,
8890+ .release = zb_sock_release,
8891+ .bind = zb_sock_bind,
8892+ .connect = zb_sock_connect,
8893+ .socketpair = sock_no_socketpair,
8894+ .accept = sock_no_accept,
8895+ .getname = sock_no_getname,
8896+ .poll = datagram_poll,
8897+ .ioctl = zb_sock_ioctl,
8898+ .listen = sock_no_listen,
8899+ .shutdown = sock_no_shutdown,
8900+ .setsockopt = sock_common_setsockopt,
8901+ .getsockopt = sock_common_getsockopt,
8902+ .sendmsg = zb_sock_sendmsg,
8903+ .recvmsg = sock_common_recvmsg,
8904+ .mmap = sock_no_mmap,
8905+ .sendpage = sock_no_sendpage,
8906+#ifdef CONFIG_COMPAT
8907+ .compat_setsockopt = compat_sock_common_setsockopt,
8908+ .compat_getsockopt = compat_sock_common_getsockopt,
8909+#endif
8910+};
8911+
8912+
8913+/*
8914+ * Create a socket. Initialise the socket, blank the addresses
8915+ * set the state.
8916+ */
8917+static int zb_create(struct net *net, struct socket *sock, int protocol)
8918+{
8919+ struct sock *sk;
8920+ int rc;
8921+ struct proto *proto;
8922+ const struct proto_ops *ops;
8923+
8924+ // FIXME: init_net
8925+ if (net != &init_net)
8926+ return -EAFNOSUPPORT;
8927+
8928+ if (sock->type == SOCK_DGRAM) {
8929+ proto = &zb_dgram_prot;
8930+ ops = &zb_dgram_ops;
8931+ }
8932+ else {
8933+ rc = -ESOCKTNOSUPPORT;
8934+ goto out;
8935+ }
8936+
8937+ rc = -ENOMEM;
8938+ sk = sk_alloc(net, PF_ZIGBEE, GFP_KERNEL, proto);
8939+ if (!sk)
8940+ goto out;
8941+ rc = 0;
8942+
8943+ sock->ops = ops;
8944+
8945+ sock_init_data(sock, sk);
8946+ // FIXME: sk->sk_destruct
8947+ sk->sk_family = PF_ZIGBEE;
8948+
8949+#if 0
8950+ /* Checksums on by default */
8951+ // FIXME:
8952+ sock_set_flag(sk, SOCK_ZAPPED);
8953+
8954+ // FIXME:
8955+ if (sk->sk_prot->hash)
8956+ sk->sk_prot->hash(sk);
8957+#endif
8958+
8959+ if (sk->sk_prot->init) {
8960+ rc = sk->sk_prot->init(sk);
8961+ if (rc)
8962+ sk_common_release(sk);
8963+ }
8964+out:
8965+ return rc;
8966+}
8967+
8968+static struct net_proto_family zb_family_ops = {
8969+ .family = PF_ZIGBEE,
8970+ .create = zb_create,
8971+ .owner = THIS_MODULE,
8972+};
8973+
8974+/*
8975+ * Main ZigBEE NWK receive routine.
8976+ */
8977+static int zb_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
8978+{
8979+ struct nwkhdr *nwkh;
8980+ u32 len;
8981+
8982+ DBG_DUMP(skb->data, skb->len);
8983+ pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
8984+ // FIXME: init_net
8985+ if (!net_eq(dev_net(dev), &init_net))
8986+ goto drop;
8987+
8988+ zb_raw_deliver(dev, skb);
8989+
8990+ if (skb->pkt_type != PACKET_OTHERHOST)
8991+ return zb_dgram_deliver(dev, skb);
8992+
8993+drop:
8994+ kfree_skb(skb);
8995+ return NET_RX_DROP;
8996+}
8997+
8998+
8999+static struct packet_type zb_packet_type = {
9000+ .type = __constant_htons(ETH_P_ZIGBEE),
9001+ .func = zb_rcv,
9002+};
9003+
9004+static int __init af_zb_init(void)
9005+{
9006+ int rc = -EINVAL;
9007+
9008+ rc = proto_register(&zb_dgram_prot, 1);
9009+ if (rc)
9010+ goto err;
9011+
9012+ /* Tell SOCKET that we are alive */
9013+ rc = sock_register(&zb_family_ops);
9014+
9015+ if (rc)
9016+ goto err;
9017+
9018+ dev_add_pack(&zb_packet_type);
9019+
9020+ rc = 0;
9021+ goto out;
9022+
9023+err:
9024+ proto_unregister(&zb_dgram_prot);
9025+out:
9026+ return rc;
9027+}
9028+
9029+static void af_zb_remove(void)
9030+{
9031+ dev_remove_pack(&zb_packet_type);
9032+ sock_unregister(PF_ZIGBEE);
9033+ proto_unregister(&zb_dgram_prot);
9034+}
9035+
9036+module_init(af_zb_init);
9037+module_exit(af_zb_remove);
9038+
9039+MODULE_LICENSE("GPL");
9040+MODULE_ALIAS_NETPROTO(PF_ZIGBEE);
9041diff --git a/net/zigbee/dgram.c b/net/zigbee/dgram.c
9042new file mode 100644
9043index 0000000..4d9b682
9044--- /dev/null
9045@@ -0,0 +1,401 @@
9046+/*
9047+ * ZigBee socket interface
9048+ *
9049+ * Copyright 2008, 2009 Siemens AG
9050+ *
9051+ * This program is free software; you can redistribute it and/or modify
9052+ * it under the terms of the GNU General Public License version 2
9053+ * as published by the Free Software Foundation.
9054+ *
9055+ * This program is distributed in the hope that it will be useful,
9056+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9057+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9058+ * GNU General Public License for more details.
9059+ *
9060+ * You should have received a copy of the GNU General Public License along
9061+ * with this program; if not, write to the Free Software Foundation, Inc.,
9062+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
9063+ *
9064+ * Written by:
9065+ * Sergey Lapin <slapin@ossfans.org>
9066+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
9067+ * Maxim Yu. Osipov <Maksim.Osipov@siemens.com>
9068+ */
9069+
9070+#include <linux/net.h>
9071+#include <linux/module.h>
9072+#include <linux/if_arp.h>
9073+#include <linux/list.h>
9074+#include <net/sock.h>
9075+//#include <net/ieee80215/netdev.h>
9076+//#include <net/ieee80215/af_ieee80215.h>
9077+//#include <net/ieee80215/mac_def.h>
9078+#include <net/zigbee/nwk.h>
9079+#include <asm/ioctls.h>
9080+
9081+static HLIST_HEAD(dgram_head);
9082+static DEFINE_RWLOCK(dgram_lock);
9083+
9084+struct dgram_sock {
9085+ struct sock sk;
9086+
9087+ int bound;
9088+ struct ieee80215_addr src_addr;
9089+ struct ieee80215_addr dst_addr;
9090+};
9091+
9092+static void dgram_hash(struct sock *sk)
9093+{
9094+ write_lock_bh(&dgram_lock);
9095+ sk_add_node(sk, &dgram_head);
9096+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
9097+ write_unlock_bh(&dgram_lock);
9098+}
9099+
9100+static void dgram_unhash(struct sock *sk)
9101+{
9102+ write_lock_bh(&dgram_lock);
9103+ if (sk_del_node_init(sk))
9104+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
9105+ write_unlock_bh(&dgram_lock);
9106+}
9107+
9108+static int dgram_init(struct sock *sk)
9109+{
9110+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9111+
9112+ ro->dst_addr.addr_type = IEEE80215_ADDR_SHORT;
9113+// ro->dst_addr.pan_id = 0xffff;
9114+ ro->dst_addr.short_addr = 0xffff;
9115+ return 0;
9116+}
9117+
9118+static void dgram_close(struct sock *sk, long timeout)
9119+{
9120+ sk_common_release(sk);
9121+}
9122+
9123+static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
9124+{
9125+ struct sockaddr_ieee80215 *addr = (struct sockaddr_ieee80215 *)uaddr;
9126+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9127+ int err = 0;
9128+
9129+ if (ro->bound)
9130+ return -EINVAL;
9131+
9132+ if (len < sizeof(*addr))
9133+ return -EINVAL;
9134+
9135+ if ((addr->family != AF_ZIGBEE) ||
9136+ (addr->addr.addr_type != IEEE80215_ADDR_SHORT))
9137+ return -EINVAL;
9138+
9139+ lock_sock(sk);
9140+ /*
9141+ * FIXME: should check here that address is not already in use
9142+ * Problem that this address is not independent - this is the
9143+ * address of the lower layer
9144+ */
9145+#if 0
9146+ dev = ieee80215_get_dev(sock_net(sk), &addr->addr);
9147+ if (!dev) {
9148+ err = -ENODEV;
9149+ goto out;
9150+ }
9151+
9152+ if (dev->type != ARPHRD_IEEE80215) {
9153+ err = -ENODEV;
9154+ goto out_put;
9155+ }
9156+#endif
9157+ memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee80215_addr));
9158+
9159+ ro->bound = 1;
9160+#if 0
9161+out_put:
9162+ dev_put(dev);
9163+out:
9164+#endif
9165+ release_sock(sk);
9166+
9167+ return err;
9168+}
9169+
9170+static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
9171+{
9172+ switch (cmd) {
9173+ case SIOCOUTQ:
9174+ {
9175+ int amount = atomic_read(&sk->sk_wmem_alloc);
9176+ return put_user(amount, (int __user *)arg);
9177+ }
9178+
9179+ case SIOCINQ:
9180+ {
9181+ struct sk_buff *skb;
9182+ unsigned long amount = 0;
9183+
9184+ spin_lock_bh(&sk->sk_receive_queue.lock);
9185+ skb = skb_peek(&sk->sk_receive_queue);
9186+ if (skb != NULL) {
9187+ /*
9188+ * We will only return the amount
9189+ * of this packet since that is all
9190+ * that will be read.
9191+ */
9192+ amount = skb->len - sizeof(struct nwkhdr);
9193+ }
9194+ spin_unlock_bh(&sk->sk_receive_queue.lock);
9195+ return put_user(amount, (int __user *)arg);
9196+
9197+ }
9198+#if 0
9199+ /* May be implement here the commands */
9200+ case IEEE80215_SIOC_NETWORK_DISCOVERY:
9201+ return ioctl_network_discovery(sk, (struct ieee80215_user_data __user *) arg);
9202+ break;
9203+ case IEEE80215_SIOC_NETWORK_FORMATION:
9204+ return ioctl_network_formation(sk, (struct ieee80215_user_data __user *) arg);
9205+ break;
9206+ case IEEE80215_SIOC_PERMIT_JOINING:
9207+ return ioctl_permit_joining(sk, (struct ieee80215_user_data __user *) arg);
9208+ break;
9209+ case IEEE80215_SIOC_START_ROUTER:
9210+ return ioctl_start_router(sk, (struct ieee80215_user_data __user *) arg);
9211+ break;
9212+ case IEEE80215_SIOC_JOIN:
9213+ return ioctl_mac_join(sk, (struct ieee80215_user_data __user *) arg);
9214+ break;
9215+ case IEEE80215_SIOC_MAC_CMD:
9216+ return ioctl_mac_cmd(sk, (struct ieee80215_user_data __user *) arg);
9217+
9218+ break;
9219+#endif
9220+ default:
9221+ return -ENOIOCTLCMD;
9222+ }
9223+}
9224+
9225+// FIXME: autobind
9226+static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
9227+ int len)
9228+{
9229+ struct sockaddr_ieee80215 *addr = (struct sockaddr_ieee80215 *)uaddr;
9230+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9231+
9232+ int err = 0;
9233+
9234+ if (len < sizeof(*addr))
9235+ return -EINVAL;
9236+
9237+ if ((addr->family != AF_ZIGBEE) ||
9238+ (addr->addr.addr_type != IEEE80215_ADDR_SHORT))
9239+ return -EINVAL;
9240+
9241+ lock_sock(sk);
9242+
9243+ if (!ro->bound) {
9244+ err = -ENETUNREACH;
9245+ goto out;
9246+ }
9247+
9248+ memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee80215_addr));
9249+
9250+out:
9251+ release_sock(sk);
9252+ return err;
9253+}
9254+
9255+static int dgram_disconnect(struct sock *sk, int flags)
9256+{
9257+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9258+
9259+ lock_sock(sk);
9260+
9261+ ro->dst_addr.addr_type = IEEE80215_ADDR_SHORT;
9262+// ro->dst_addr.pan_id = 0xffff;
9263+ ro->dst_addr.short_addr = 0xffff;
9264+
9265+ release_sock(sk);
9266+
9267+ return 0;
9268+}
9269+
9270+static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
9271+ size_t size)
9272+{
9273+ struct net_device *dev;
9274+ unsigned mtu;
9275+ struct sk_buff *skb;
9276+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9277+
9278+ int err;
9279+ struct ieee80215_priv *hw;
9280+
9281+ if (msg->msg_flags & MSG_OOB) {
9282+ pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
9283+ return -EOPNOTSUPP;
9284+ }
9285+
9286+ if (!ro->bound)
9287+ dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE80215);
9288+ else
9289+ dev = ieee80215_get_dev(sock_net(sk), &ro->src_addr);
9290+
9291+ if (!dev) {
9292+ pr_debug("no dev\n");
9293+ return -ENXIO;
9294+ }
9295+ hw = ieee80215_slave_get_hw(dev);
9296+ mtu = dev->mtu;
9297+ pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
9298+
9299+ skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + size, msg->msg_flags & MSG_DONTWAIT,
9300+ &err);
9301+ if (!skb) {
9302+ dev_put(dev);
9303+ return err;
9304+ }
9305+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
9306+
9307+ skb_reset_network_header(skb);
9308+
9309+ MAC_CB(skb)->flags = IEEE80215_FC_TYPE_DATA | MAC_CB_FLAG_ACKREQ;
9310+ MAC_CB(skb)->seq = hw->dsn;
9311+ err = dev_hard_header(skb, dev, ETH_P_IEEE80215, &ro->dst_addr, ro->bound ? &ro->src_addr : NULL, size);
9312+ if (err < 0) {
9313+ kfree_skb(skb);
9314+ dev_put(dev);
9315+ return err;
9316+ }
9317+
9318+ skb_reset_mac_header(skb);
9319+
9320+ err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
9321+ if (err < 0) {
9322+ kfree_skb(skb);
9323+ dev_put(dev);
9324+ return err;
9325+ }
9326+
9327+ if (size > mtu) {
9328+ pr_debug("size = %u, mtu = %u\n", size, mtu);
9329+ return -EINVAL;
9330+ }
9331+
9332+ skb->dev = dev;
9333+ skb->sk = sk;
9334+ skb->protocol = htons(ETH_P_IEEE80215);
9335+
9336+ err = dev_queue_xmit(skb);
9337+ hw->dsn++;
9338+
9339+ dev_put(dev);
9340+
9341+ if (err)
9342+ return err;
9343+
9344+ return size;
9345+}
9346+
9347+static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
9348+ size_t len, int noblock, int flags, int *addr_len)
9349+{
9350+ size_t copied = 0;
9351+ int err = -EOPNOTSUPP;
9352+ struct sk_buff *skb;
9353+
9354+ skb = skb_recv_datagram(sk, flags, noblock, &err);
9355+ if (!skb)
9356+ goto out;
9357+
9358+ copied = skb->len;
9359+ if (len < copied) {
9360+ msg->msg_flags |= MSG_TRUNC;
9361+ copied = len;
9362+ }
9363+
9364+ // FIXME: skip headers if necessary ?!
9365+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
9366+ if (err)
9367+ goto done;
9368+
9369+ sock_recv_timestamp(msg, sk, skb);
9370+
9371+ if (flags & MSG_TRUNC)
9372+ copied = skb->len;
9373+done:
9374+ skb_free_datagram(sk, skb);
9375+out:
9376+ if (err)
9377+ return err;
9378+ return copied;
9379+}
9380+
9381+static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
9382+{
9383+ if (sock_queue_rcv_skb(sk, skb) < 0) {
9384+ atomic_inc(&sk->sk_drops);
9385+ kfree_skb(skb);
9386+ return NET_RX_DROP;
9387+ }
9388+
9389+ return NET_RX_SUCCESS;
9390+}
9391+
9392+int ieee80215_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
9393+{
9394+ struct sock *sk, *prev = NULL;
9395+ struct hlist_node*node;
9396+ int ret = NET_RX_SUCCESS;
9397+
9398+ /* Data frame processing */
9399+
9400+ read_lock(&dgram_lock);
9401+ sk_for_each(sk, node, &dgram_head) {
9402+ struct dgram_sock *ro = container_of(sk, struct dgram_sock, sk);
9403+ if (!ro->bound ||
9404+ (ro->src_addr.addr_type == IEEE80215_ADDR_LONG &&
9405+ !memcmp(ro->src_addr.hwaddr, dev->dev_addr, IEEE80215_ADDR_LEN)) ||
9406+ (ro->src_addr.addr_type == IEEE80215_ADDR_SHORT &&
9407+ ieee80215_dev_get_pan_id(dev) == ro->src_addr.pan_id &&
9408+ ieee80215_dev_get_short_addr(dev) == ro->src_addr.short_addr)) {
9409+ if (prev) {
9410+ struct sk_buff *clone;
9411+ clone = skb_clone(skb, GFP_ATOMIC);
9412+ if (clone)
9413+ dgram_rcv_skb(prev, clone);
9414+ }
9415+
9416+ prev = sk;
9417+ }
9418+ }
9419+
9420+ if (prev)
9421+ dgram_rcv_skb(prev, skb);
9422+ else {
9423+ kfree_skb(skb);
9424+ ret = NET_RX_DROP;
9425+ }
9426+ read_unlock(&dgram_lock);
9427+
9428+ return ret;
9429+}
9430+
9431+struct proto ieee80215_dgram_prot = {
9432+ .name = "ZigBEE",
9433+ .owner = THIS_MODULE,
9434+ .obj_size = sizeof(struct dgram_sock),
9435+ .init = dgram_init,
9436+ .close = dgram_close,
9437+ .bind = dgram_bind,
9438+ .sendmsg = dgram_sendmsg,
9439+ .recvmsg = dgram_recvmsg,
9440+ .hash = dgram_hash,
9441+ .unhash = dgram_unhash,
9442+ .connect = dgram_connect,
9443+ .disconnect = dgram_disconnect,
9444+ .ioctl = dgram_ioctl,
9445+};
9446+
9447--
94481.7.5.4
9449
target/linux/xburst/patches-3.3/800-WPAN-patches.patch
1From ca7f714fc8c9981eda5d85594333f955f75510f7 Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Tue, 5 Jun 2012 11:32:43 +0800
4Subject: [PATCH 1/3] 002
5
6---
7 drivers/ieee802154/Kconfig | 55 +++++++++++++++++++++++++++++++++++++-
8 drivers/ieee802154/Makefile | 11 ++++++++
9 drivers/ieee802154/fakehard.c | 12 ++++++++-
10 include/linux/if.h | 2 +
11 include/linux/if_arp.h | 2 +
12 include/linux/nl802154.h | 10 +++++-
13 include/net/ieee802154_netdev.h | 17 ++++++++++--
14 include/net/wpan-phy.h | 8 +++--
15 net/Kconfig | 2 +
16 net/Makefile | 1 +
17 net/ieee802154/Kconfig | 8 +++++
18 net/ieee802154/Makefile | 3 ++
19 net/ieee802154/dgram.c | 3 +-
20 net/ieee802154/ieee802154.h | 4 +++
21 net/ieee802154/nl-mac.c | 2 +-
22 net/ieee802154/nl-phy.c | 20 ++++++++++++--
23 net/ieee802154/nl_policy.c | 1 +
24 net/ieee802154/wpan-class.c | 2 +-
25 18 files changed, 145 insertions(+), 18 deletions(-)
26
27diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig
28index 9b9f43a..5345e40 100644
29--- a/drivers/ieee802154/Kconfig
30@@ -10,13 +10,64 @@ menuconfig IEEE802154_DRIVERS
31       If you say N, all options in this submenu will be skipped and
32       disabled.
33
34+config IEEE802154_DRIVER_DEBUG
35+ bool "Driver debugging messages"
36+ depends on IEEE802154_DRIVERS
37+ default y
38+ help
39+ Say Y here to make the IEEE 802.15.4 drivers generate extensive
40+ debugging messages.
41+
42 config IEEE802154_FAKEHARD
43     tristate "Fake LR-WPAN driver with several interconnected devices"
44     depends on IEEE802154_DRIVERS
45     ---help---
46       Say Y here to enable the fake driver that serves as an example
47- of HardMAC device driver.
48+ of HardMAC device driver.
49
50- This driver can also be built as a module. To do so say M here.
51+ This driver can also be built as a module. To do so say M here.
52       The module will be called 'fakehard'.
53
54+
55+config IEEE802154_FAKELB
56+ depends on IEEE802154_DRIVERS && MAC802154
57+ tristate "Fake LR-WPAN driver with several interconnected devices"
58+ ---help---
59+ Say Y here to enable the fake driver that can emulate a net
60+ of several interconnected radio devices.
61+
62+ This driver can also be built as a module. To do so say M here.
63+ The module will be called 'fakelb'.
64+
65+config IEEE802154_SERIAL
66+ depends on IEEE802154_DRIVERS && MAC802154
67+ tristate "Simple LR-WPAN UART driver"
68+
69+config IEEE802154_AT86RF230
70+ depends on IEEE802154_DRIVERS && MAC802154
71+ tristate "AT86RF230 transceiver driver"
72+ depends on SPI
73+
74+config SPI_ATBEN
75+ tristate "ATBEN 8:10 SPI interface"
76+ depends on JZ4740_QI_LB60 && IEEE802154_AT86RF230
77+ help
78+ Bit-banging SPI driver for the 8:10 interface of the Ben NanoNote
79+ when equipped with an ATBEN board.
80+
81+config SPI_ATUSB
82+ tristate "ATUSB SPI interface"
83+ depends on USB && IEEE802154_AT86RF230
84+ help
85+ SPI-over-USB driver for the ATUSB IEEE 802.15.4 board.
86+
87+config IEEE802154_CC2420
88+ tristate "CC2420 driver"
89+ depends on SPI
90+ depends on IEEE802154_DRIVERS
91+
92+config IEEE802154_ADF7242
93+ tristate "ADF7242 transceiver driver"
94+ depends on IEEE802154_DRIVERS && MAC802154
95+ depends on SPI
96+
97diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
98index 800a389..4f669bc 100644
99--- a/drivers/ieee802154/Makefile
100@@ -1 +1,12 @@
101 obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
102+obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
103+obj-$(CONFIG_IEEE802154_SERIAL) += serial.o
104+obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
105+obj-$(CONFIG_IEEE802154_CC2420) += cc2420.o
106+obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
107+obj-$(CONFIG_SPI_ATBEN) += spi_atben.o
108+obj-$(CONFIG_SPI_ATUSB) += spi_atusb.o
109+
110+ccflags-y := -DDEBUG -DCONFIG_FFD
111+ccflags-$(CONFIG_IEEE802154_DRIVER_DEBUG) += -DDEBUG
112+ccflags-y += -DCONFIG_FFD
113diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
114index 73d4531..996e1db 100644
115--- a/drivers/ieee802154/fakehard.c
116@@ -259,7 +259,7 @@ static struct ieee802154_mlme_ops fake_mlme = {
117     .start_req = fake_start_req,
118     .scan_req = fake_scan_req,
119
120- .get_phy = fake_get_phy,
121+ .wpan_ops.get_phy = fake_get_phy,
122
123     .get_pan_id = fake_get_pan_id,
124     .get_short_addr = fake_get_short_addr,
125@@ -391,6 +391,16 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
126     priv = netdev_priv(dev);
127     priv->phy = phy;
128
129+ /*
130+ * If the name is a format string the caller wants us to do a
131+ * name allocation.
132+ */
133+ if (strchr(dev->name, '%')) {
134+ err = dev_alloc_name(dev, dev->name);
135+ if (err < 0)
136+ goto out;
137+ }
138+
139     wpan_phy_set_dev(phy, &pdev->dev);
140     SET_NETDEV_DEV(dev, &phy->dev);
141
142diff --git a/include/linux/if.h b/include/linux/if.h
143index cffa754..9f402a1 100644
144--- a/include/linux/if.h
145@@ -82,6 +82,8 @@
146 #define IFF_TEAM_PORT 0x40000 /* device used as team port */
147 #define IFF_NO_IP_ALIGN 0x80000 /* do not ip-align allocated rx pkts */
148
149+#define IFF_IEEE802154_COORD 0x400 /* IEEE802.15.4 PAN coordinator */
150+
151 #define IF_GET_IFACE 0x0001 /* for querying only */
152 #define IF_GET_PROTO 0x0002
153
154diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
155index 6d722f4..47a57d8 100644
156--- a/include/linux/if_arp.h
157@@ -87,6 +87,8 @@
158 #define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */
159 #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */
160 #define ARPHRD_IEEE802154 804
161+#define ARPHRD_IEEE802154_MONITOR 805
162+#define ARPHRD_SMAC 806 /* Freescale Simple MAC */
163
164 #define ARPHRD_PHONET 820 /* PhoNet media type */
165 #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */
166diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
167index 33d9f51..a379fc7 100644
168--- a/include/linux/nl802154.h
169@@ -68,14 +68,13 @@ enum {
170     IEEE802154_ATTR_CHANNEL_PAGE_LIST,
171
172     IEEE802154_ATTR_PHY_NAME,
173+ IEEE802154_ATTR_DEV_TYPE,
174
175     __IEEE802154_ATTR_MAX,
176 };
177
178 #define IEEE802154_ATTR_MAX (__IEEE802154_ATTR_MAX - 1)
179
180-extern const struct nla_policy ieee802154_policy[];
181-
182 /* commands */
183 /* REQ should be responded with CONF
184  * and INDIC with RESP
185@@ -126,4 +125,11 @@ enum {
186
187 #define IEEE802154_CMD_MAX (__IEEE802154_CMD_MAX - 1)
188
189+enum {
190+ IEEE802154_DEV_WPAN,
191+ IEEE802154_DEV_MONITOR,
192+ IEEE802154_DEV_SMAC,
193+ __IEEE802154_DEV_MAX,
194+};
195+
196 #endif
197diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
198index 5743055..e12ce9a 100644
199--- a/include/net/ieee802154_netdev.h
200@@ -26,6 +26,8 @@
201 #ifndef IEEE802154_NETDEVICE_H
202 #define IEEE802154_NETDEVICE_H
203
204+#include <net/af_ieee802154.h>
205+
206 /*
207  * A control block of skb passed between the ARPHRD_IEEE802154 device
208  * and other stack parts.
209@@ -81,7 +83,12 @@ struct wpan_phy;
210  * get_phy should increment the reference counting on returned phy.
211  * Use wpan_wpy_put to put that reference.
212  */
213+struct simple_mlme_ops {
214+ struct wpan_phy *(*get_phy)(const struct net_device *dev);
215+};
216 struct ieee802154_mlme_ops {
217+ struct simple_mlme_ops wpan_ops;
218+
219     int (*assoc_req)(struct net_device *dev,
220             struct ieee802154_addr *addr,
221             u8 channel, u8 page, u8 cap);
222@@ -98,8 +105,6 @@ struct ieee802154_mlme_ops {
223     int (*scan_req)(struct net_device *dev,
224             u8 type, u32 channels, u8 page, u8 duration);
225
226- struct wpan_phy *(*get_phy)(const struct net_device *dev);
227-
228     /*
229      * FIXME: these should become the part of PIB/MIB interface.
230      * However we still don't have IB interface of any kind
231@@ -110,12 +115,18 @@ struct ieee802154_mlme_ops {
232     u8 (*get_bsn)(const struct net_device *dev);
233 };
234
235-static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops(
236+static inline struct simple_mlme_ops *simple_mlme_ops(
237         const struct net_device *dev)
238 {
239     return dev->ml_priv;
240 }
241
242+static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops(
243+ const struct net_device *dev)
244+{
245+ return container_of(dev->ml_priv, struct ieee802154_mlme_ops, wpan_ops);
246+}
247+
248 #endif
249
250
251diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
252index d86fffd..9e119c5 100644
253--- a/include/net/wpan-phy.h
254@@ -24,17 +24,19 @@
255 #include <linux/netdevice.h>
256 #include <linux/mutex.h>
257
258+#define WPAN_NUM_PAGES 32
259+
260 struct wpan_phy {
261     struct mutex pib_lock;
262
263     /*
264- * This is a PIB according to 802.15.4-2006.
265+ * This is a PIB acording to 802.15.4-2006.
266      * We do not provide timing-related variables, as they
267      * aren't used outside of driver
268      */
269     u8 current_channel;
270     u8 current_page;
271- u32 channels_supported[32];
272+ u32 channels_supported[WPAN_NUM_PAGES];
273     u8 transmit_power;
274     u8 cca_mode;
275
276@@ -42,7 +44,7 @@ struct wpan_phy {
277     int idx;
278
279     struct net_device *(*add_iface)(struct wpan_phy *phy,
280- const char *name);
281+ const char *name, int type);
282     void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
283
284     char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
285diff --git a/net/Kconfig b/net/Kconfig
286index b3904e8..578eb11 100644
287--- a/net/Kconfig
288@@ -217,6 +217,8 @@ source "net/econet/Kconfig"
289 source "net/wanrouter/Kconfig"
290 source "net/phonet/Kconfig"
291 source "net/ieee802154/Kconfig"
292+source "net/mac802154/Kconfig"
293+source "net/zigbee/Kconfig"
294 source "net/sched/Kconfig"
295 source "net/dcb/Kconfig"
296 source "net/dns_resolver/Kconfig"
297diff --git a/net/Makefile b/net/Makefile
298index ad432fa..2a97cde 100644
299--- a/net/Makefile
300@@ -60,6 +60,7 @@ ifneq ($(CONFIG_DCB),)
301 obj-y += dcb/
302 endif
303 obj-$(CONFIG_IEEE802154) += ieee802154/
304+obj-$(CONFIG_MAC802154) += mac802154/
305
306 ifeq ($(CONFIG_NET),y)
307 obj-$(CONFIG_SYSCTL) += sysctl_net.o
308diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig
309index 7dee650..3dea3c1 100644
310--- a/net/ieee802154/Kconfig
311@@ -16,3 +16,11 @@ config IEEE802154_6LOWPAN
312     depends on IEEE802154 && IPV6
313     ---help---
314     IPv6 compression over IEEE 802.15.4.
315+
316+config IEEE802154_PROTO_DEBUG
317+ bool "IEEE 802.15.4 protocol stack debugging messages"
318+ depends on IEEE802154
319+ default y
320+ help
321+ Say Y here to make the IEEE 802.15.4 protocol stack generate
322+ extensive debugging messages.
323diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
324index d7716d6..e2b6735 100644
325--- a/net/ieee802154/Makefile
326@@ -3,3 +3,6 @@ obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
327
328 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
329 af_802154-y := af_ieee802154.o raw.o dgram.o
330+
331+ccflags-$(CONFIG_IEEE802154_PROTO_DEBUG) += -DDEBUG
332+ccflags-y += -Wall
333diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
334index 1b09eaa..7883fa6 100644
335--- a/net/ieee802154/dgram.c
336@@ -130,8 +130,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
337     switch (cmd) {
338     case SIOCOUTQ:
339     {
340- int amount = sk_wmem_alloc_get(sk);
341-
342+ int amount = atomic_read(&sk->sk_wmem_alloc);
343         return put_user(amount, (int __user *)arg);
344     }
345
346diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
347index aadec42..e78d6c6 100644
348--- a/net/ieee802154/ieee802154.h
349@@ -21,6 +21,10 @@
350 int __init ieee802154_nl_init(void);
351 void __exit ieee802154_nl_exit(void);
352
353+#include <net/netlink.h>
354+
355+extern const struct nla_policy ieee802154_policy[];
356+
357 #define IEEE802154_OP(_cmd, _func) \
358     { \
359         .cmd = _cmd, \
360diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
361index adaf462..1d23aa6 100644
362--- a/net/ieee802154/nl-mac.c
363@@ -263,7 +263,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid,
364     if (!hdr)
365         goto out;
366
367- phy = ieee802154_mlme_ops(dev)->get_phy(dev);
368+ phy = simple_mlme_ops(dev)->get_phy(dev);
369     BUG_ON(!phy);
370
371     NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
372diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
373index c64a38d..76ef7a3 100644
374--- a/net/ieee802154/nl-phy.c
375@@ -57,7 +57,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
376
377     NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, phy->current_page);
378     NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel);
379- for (i = 0; i < 32; i++) {
380+ for (i = 0; i < WPAN_NUM_PAGES; i++) {
381         if (phy->channels_supported[i])
382             buf[pages++] = phy->channels_supported[i] | (i << 27);
383     }
384@@ -179,6 +179,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
385     const char *devname;
386     int rc = -ENOBUFS;
387     struct net_device *dev;
388+ int type = IEEE802154_DEV_WPAN;
389
390     pr_debug("%s\n", __func__);
391
392@@ -201,6 +202,19 @@ static int ieee802154_add_iface(struct sk_buff *skb,
393     if (strlen(devname) >= IFNAMSIZ)
394         return -ENAMETOOLONG;
395
396+ if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
397+ nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
398+ IEEE802154_ADDR_LEN) {
399+ return -EINVAL;
400+ }
401+
402+ if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) {
403+ type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]);
404+ if (type > __IEEE802154_DEV_MAX) {
405+ return -EINVAL;
406+ }
407+ }
408+
409     phy = wpan_phy_find(name);
410     if (!phy)
411         return -ENODEV;
412@@ -221,7 +235,7 @@ static int ieee802154_add_iface(struct sk_buff *skb,
413         goto nla_put_failure;
414     }
415
416- dev = phy->add_iface(phy, devname);
417+ dev = phy->add_iface(phy, devname, type);
418     if (IS_ERR(dev)) {
419         rc = PTR_ERR(dev);
420         goto nla_put_failure;
421@@ -288,7 +302,7 @@ static int ieee802154_del_iface(struct sk_buff *skb,
422     if (!dev)
423         return -ENODEV;
424
425- phy = ieee802154_mlme_ops(dev)->get_phy(dev);
426+ phy = simple_mlme_ops(dev)->get_phy(dev);
427     BUG_ON(!phy);
428
429     rc = -EINVAL;
430diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
431index 6adda4d..235cd65 100644
432--- a/net/ieee802154/nl_policy.c
433@@ -28,6 +28,7 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
434     [IEEE802154_ATTR_DEV_NAME] = { .type = NLA_STRING, },
435     [IEEE802154_ATTR_DEV_INDEX] = { .type = NLA_U32, },
436     [IEEE802154_ATTR_PHY_NAME] = { .type = NLA_STRING, },
437+ [IEEE802154_ATTR_DEV_TYPE] = { .type = NLA_U8, },
438
439     [IEEE802154_ATTR_STATUS] = { .type = NLA_U8, },
440     [IEEE802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
441diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
442index 1627ef2..380fe1a 100644
443--- a/net/ieee802154/wpan-class.c
444@@ -56,7 +56,7 @@ static ssize_t channels_supported_show(struct device *dev,
445     int i, len = 0;
446
447     mutex_lock(&phy->pib_lock);
448- for (i = 0; i < 32; i++) {
449+ for (i = 0; i < WPAN_NUM_PAGES; i++) {
450         ret = snprintf(buf + len, PAGE_SIZE - len,
451                 "%#09x\n", phy->channels_supported[i]);
452         if (ret < 0)
453--
4541.7.5.4
455

Archive Download the corresponding diff file



interactive