ieee802154.h 8.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * IEEE802.15.4-2003 specification
 *
 * Copyright (C) 2007, 2008 Siemens AG
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Written by:
 * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
 * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
 * Maxim Osipov <maxim.osipov@siemens.com>
 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
20
 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
21 22
 */

23 24
#ifndef LINUX_IEEE802154_H
#define LINUX_IEEE802154_H
25

26
#include <linux/types.h>
27
#include <linux/random.h>
A
Alexander Aring 已提交
28
#include <asm/byteorder.h>
29

30
#define IEEE802154_MTU			127
31 32
#define IEEE802154_ACK_PSDU_LEN		5
#define IEEE802154_MIN_PSDU_LEN		9
33
#define IEEE802154_FCS_LEN		2
34

35
#define IEEE802154_PAN_ID_BROADCAST	0xffff
36 37
#define IEEE802154_ADDR_SHORT_BROADCAST	0xffff
#define IEEE802154_ADDR_SHORT_UNSPEC	0xfffe
38

39 40
#define IEEE802154_EXTENDED_ADDR_LEN	8

41 42
#define IEEE802154_LIFS_PERIOD		40
#define IEEE802154_SIFS_PERIOD		12
43
#define IEEE802154_MAX_SIFS_FRAME_SIZE	18
44

45 46 47
#define IEEE802154_MAX_CHANNEL		26
#define IEEE802154_MAX_PAGE		31

48 49 50 51 52 53 54 55 56 57 58 59 60
#define IEEE802154_FC_TYPE_BEACON	0x0	/* Frame is beacon */
#define	IEEE802154_FC_TYPE_DATA		0x1	/* Frame is data */
#define IEEE802154_FC_TYPE_ACK		0x2	/* Frame is acknowledgment */
#define IEEE802154_FC_TYPE_MAC_CMD	0x3	/* Frame is MAC command */

#define IEEE802154_FC_TYPE_SHIFT		0
#define IEEE802154_FC_TYPE_MASK		((1 << 3) - 1)
#define IEEE802154_FC_TYPE(x)		((x & IEEE802154_FC_TYPE_MASK) >> IEEE802154_FC_TYPE_SHIFT)
#define IEEE802154_FC_SET_TYPE(v, x)	do {	\
	v = (((v) & ~IEEE802154_FC_TYPE_MASK) | \
	    (((x) << IEEE802154_FC_TYPE_SHIFT) & IEEE802154_FC_TYPE_MASK)); \
	} while (0)

61 62 63 64 65 66 67 68
#define IEEE802154_FC_SECEN_SHIFT	3
#define IEEE802154_FC_SECEN		(1 << IEEE802154_FC_SECEN_SHIFT)
#define IEEE802154_FC_FRPEND_SHIFT	4
#define IEEE802154_FC_FRPEND		(1 << IEEE802154_FC_FRPEND_SHIFT)
#define IEEE802154_FC_ACK_REQ_SHIFT	5
#define IEEE802154_FC_ACK_REQ		(1 << IEEE802154_FC_ACK_REQ_SHIFT)
#define IEEE802154_FC_INTRA_PAN_SHIFT	6
#define IEEE802154_FC_INTRA_PAN		(1 << IEEE802154_FC_INTRA_PAN_SHIFT)
69 70 71 72 73 74

#define IEEE802154_FC_SAMODE_SHIFT	14
#define IEEE802154_FC_SAMODE_MASK	(3 << IEEE802154_FC_SAMODE_SHIFT)
#define IEEE802154_FC_DAMODE_SHIFT	10
#define IEEE802154_FC_DAMODE_MASK	(3 << IEEE802154_FC_DAMODE_SHIFT)

75 76 77 78
#define IEEE802154_FC_VERSION_SHIFT	12
#define IEEE802154_FC_VERSION_MASK	(3 << IEEE802154_FC_VERSION_SHIFT)
#define IEEE802154_FC_VERSION(x)	((x & IEEE802154_FC_VERSION_MASK) >> IEEE802154_FC_VERSION_SHIFT)

79 80 81 82 83 84
#define IEEE802154_FC_SAMODE(x)		\
	(((x) & IEEE802154_FC_SAMODE_MASK) >> IEEE802154_FC_SAMODE_SHIFT)

#define IEEE802154_FC_DAMODE(x)		\
	(((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT)

85 86 87 88 89 90 91 92 93 94 95 96
#define IEEE802154_SCF_SECLEVEL_MASK		7
#define IEEE802154_SCF_SECLEVEL_SHIFT		0
#define IEEE802154_SCF_SECLEVEL(x)		(x & IEEE802154_SCF_SECLEVEL_MASK)
#define IEEE802154_SCF_KEY_ID_MODE_SHIFT	3
#define IEEE802154_SCF_KEY_ID_MODE_MASK		(3 << IEEE802154_SCF_KEY_ID_MODE_SHIFT)
#define IEEE802154_SCF_KEY_ID_MODE(x)		\
	((x & IEEE802154_SCF_KEY_ID_MODE_MASK) >> IEEE802154_SCF_KEY_ID_MODE_SHIFT)

#define IEEE802154_SCF_KEY_IMPLICIT		0
#define IEEE802154_SCF_KEY_INDEX		1
#define IEEE802154_SCF_KEY_SHORT_INDEX		2
#define IEEE802154_SCF_KEY_HW_INDEX		3
97

98 99 100 101 102 103 104 105 106
#define IEEE802154_SCF_SECLEVEL_NONE		0
#define IEEE802154_SCF_SECLEVEL_MIC32		1
#define IEEE802154_SCF_SECLEVEL_MIC64		2
#define IEEE802154_SCF_SECLEVEL_MIC128		3
#define IEEE802154_SCF_SECLEVEL_ENC		4
#define IEEE802154_SCF_SECLEVEL_ENC_MIC32	5
#define IEEE802154_SCF_SECLEVEL_ENC_MIC64	6
#define IEEE802154_SCF_SECLEVEL_ENC_MIC128	7

107 108 109
/* MAC footer size */
#define IEEE802154_MFR_SIZE	2 /* 2 octets */

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
/* MAC's Command Frames Identifiers */
#define IEEE802154_CMD_ASSOCIATION_REQ		0x01
#define IEEE802154_CMD_ASSOCIATION_RESP		0x02
#define IEEE802154_CMD_DISASSOCIATION_NOTIFY	0x03
#define IEEE802154_CMD_DATA_REQ			0x04
#define IEEE802154_CMD_PANID_CONFLICT_NOTIFY	0x05
#define IEEE802154_CMD_ORPHAN_NOTIFY		0x06
#define IEEE802154_CMD_BEACON_REQ		0x07
#define IEEE802154_CMD_COORD_REALIGN_NOTIFY	0x08
#define IEEE802154_CMD_GTS_REQ			0x09

/*
 * The return values of MAC operations
 */
enum {
	/*
	 * The requested operation was completed successfully.
	 * For a transmission request, this value indicates
	 * a successful transmission.
	 */
	IEEE802154_SUCCESS = 0x0,

	/* The beacon was lost following a synchronization request. */
	IEEE802154_BEACON_LOSS = 0xe0,
	/*
	 * A transmission could not take place due to activity on the
	 * channel, i.e., the CSMA-CA mechanism has failed.
	 */
	IEEE802154_CHNL_ACCESS_FAIL = 0xe1,
	/* The GTS request has been denied by the PAN coordinator. */
	IEEE802154_DENINED = 0xe2,
	/* The attempt to disable the transceiver has failed. */
	IEEE802154_DISABLE_TRX_FAIL = 0xe3,
	/*
	 * The received frame induces a failed security check according to
	 * the security suite.
	 */
	IEEE802154_FAILED_SECURITY_CHECK = 0xe4,
	/*
	 * The frame resulting from secure processing has a length that is
	 * greater than aMACMaxFrameSize.
	 */
	IEEE802154_FRAME_TOO_LONG = 0xe5,
	/*
	 * The requested GTS transmission failed because the specified GTS
	 * either did not have a transmit GTS direction or was not defined.
	 */
	IEEE802154_INVALID_GTS = 0xe6,
	/*
	 * A request to purge an MSDU from the transaction queue was made using
	 * an MSDU handle that was not found in the transaction table.
	 */
	IEEE802154_INVALID_HANDLE = 0xe7,
	/* A parameter in the primitive is out of the valid range.*/
	IEEE802154_INVALID_PARAMETER = 0xe8,
	/* No acknowledgment was received after aMaxFrameRetries. */
	IEEE802154_NO_ACK = 0xe9,
	/* A scan operation failed to find any network beacons.*/
	IEEE802154_NO_BEACON = 0xea,
	/* No response data were available following a request. */
	IEEE802154_NO_DATA = 0xeb,
	/* The operation failed because a short address was not allocated. */
	IEEE802154_NO_SHORT_ADDRESS = 0xec,
	/*
	 * A receiver enable request was unsuccessful because it could not be
	 * completed within the CAP.
	 */
	IEEE802154_OUT_OF_CAP = 0xed,
	/*
	 * A PAN identifier conflict has been detected and communicated to the
	 * PAN coordinator.
	 */
	IEEE802154_PANID_CONFLICT = 0xee,
	/* A coordinator realignment command has been received. */
	IEEE802154_REALIGMENT = 0xef,
	/* The transaction has expired and its information discarded. */
	IEEE802154_TRANSACTION_EXPIRED = 0xf0,
	/* There is no capacity to store the transaction. */
	IEEE802154_TRANSACTION_OVERFLOW = 0xf1,
	/*
	 * The transceiver was in the transmitter enabled state when the
	 * receiver was requested to be enabled.
	 */
	IEEE802154_TX_ACTIVE = 0xf2,
	/* The appropriate key is not available in the ACL. */
	IEEE802154_UNAVAILABLE_KEY = 0xf3,
	/*
	 * A SET/GET request was issued with the identifier of a PIB attribute
	 * that is not supported.
	 */
	IEEE802154_UNSUPPORTED_ATTR = 0xf4,
	/*
	 * A request to perform a scan operation failed because the MLME was
	 * in the process of performing a previously initiated scan operation.
	 */
	IEEE802154_SCAN_IN_PROGRESS = 0xfc,
};

208 209
/**
 * ieee802154_is_valid_psdu_len - check if psdu len is valid
210 211 212 213 214 215
 * available lengths:
 *	0-4	Reserved
 *	5	MPDU (Acknowledgment)
 *	6-8	Reserved
 *	9-127	MPDU
 *
216 217 218 219
 * @len: psdu len with (MHR + payload + MFR)
 */
static inline bool ieee802154_is_valid_psdu_len(const u8 len)
{
220 221
	return (len == IEEE802154_ACK_PSDU_LEN ||
		(len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU));
222
}
223

224 225 226 227 228 229 230 231 232 233 234
/**
 * ieee802154_is_valid_psdu_len - check if extended addr is valid
 * @addr: extended addr to check
 */
static inline bool ieee802154_is_valid_extended_addr(const __le64 addr)
{
	/* These EUI-64 addresses are reserved by IEEE. 0xffffffffffffffff
	 * is used internally as extended to short address broadcast mapping.
	 * This is currently a workaround because neighbor discovery can't
	 * deal with short addresses types right now.
	 */
235
	return ((addr != cpu_to_le64(0x0000000000000000ULL)) &&
A
Alexander Aring 已提交
236
		(addr != cpu_to_le64(0xffffffffffffffffULL)));
237 238
}

239 240 241 242 243 244 245 246 247 248 249 250 251
/**
 * ieee802154_random_extended_addr - generates a random extended address
 * @addr: extended addr pointer to place the random address
 */
static inline void ieee802154_random_extended_addr(__le64 *addr)
{
	get_random_bytes(addr, IEEE802154_EXTENDED_ADDR_LEN);

	/* toggle some bit if we hit an invalid extended addr */
	if (!ieee802154_is_valid_extended_addr(*addr))
		((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] ^= 0x01;
}

252
#endif /* LINUX_IEEE802154_H */