ieee802154.h 10.7 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>
28

29
#define IEEE802154_MTU			127
30 31
#define IEEE802154_ACK_PSDU_LEN		5
#define IEEE802154_MIN_PSDU_LEN		9
32
#define IEEE802154_FCS_LEN		2
33 34 35 36 37 38 39 40 41 42 43
#define IEEE802154_MAX_AUTH_TAG_LEN	16

/*  General MAC frame format:
 *  2 bytes: Frame Control
 *  1 byte:  Sequence Number
 * 20 bytes: Addressing fields
 * 14 bytes: Auxiliary Security Header
 */
#define IEEE802154_MAX_HEADER_LEN	(2 + 1 + 20 + 14)
#define IEEE802154_MIN_HEADER_LEN	(IEEE802154_ACK_PSDU_LEN - \
					 IEEE802154_FCS_LEN)
44

45
#define IEEE802154_PAN_ID_BROADCAST	0xffff
46 47
#define IEEE802154_ADDR_SHORT_BROADCAST	0xffff
#define IEEE802154_ADDR_SHORT_UNSPEC	0xfffe
48

49
#define IEEE802154_EXTENDED_ADDR_LEN	8
50
#define IEEE802154_SHORT_ADDR_LEN	2
51

52 53
#define IEEE802154_LIFS_PERIOD		40
#define IEEE802154_SIFS_PERIOD		12
54
#define IEEE802154_MAX_SIFS_FRAME_SIZE	18
55

56 57 58
#define IEEE802154_MAX_CHANNEL		26
#define IEEE802154_MAX_PAGE		31

59 60 61 62 63 64 65 66 67 68 69 70 71
#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)

72 73 74 75 76 77 78 79
#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)
80 81 82 83 84 85

#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)

86 87 88 89
#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)

90 91 92 93 94 95
#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)

96 97 98 99 100 101 102 103 104 105 106 107
#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
108

109 110 111 112 113 114 115 116 117
#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

118 119 120
/* MAC footer size */
#define IEEE802154_MFR_SIZE	2 /* 2 octets */

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 208 209 210 211 212 213 214 215 216 217 218
/* 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,
};

219 220
/* frame control handling */
#define IEEE802154_FCTL_FTYPE		0x0003
221
#define IEEE802154_FCTL_ACKREQ		0x0020
222
#define IEEE802154_FCTL_SECEN		0x0004
223 224 225 226 227 228 229 230 231 232 233 234 235 236
#define IEEE802154_FCTL_INTRA_PAN	0x0040

#define IEEE802154_FTYPE_DATA		0x0001

/*
 * ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA
 * @fc: frame control bytes in little-endian byteorder
 */
static inline int ieee802154_is_data(__le16 fc)
{
	return (fc & cpu_to_le16(IEEE802154_FCTL_FTYPE)) ==
		cpu_to_le16(IEEE802154_FTYPE_DATA);
}

237 238 239 240 241 242 243 244 245
/**
 * ieee802154_is_secen - check if Security bit is set
 * @fc: frame control bytes in little-endian byteorder
 */
static inline bool ieee802154_is_secen(__le16 fc)
{
	return fc & cpu_to_le16(IEEE802154_FCTL_SECEN);
}

246 247 248 249 250 251 252 253 254
/**
 * ieee802154_is_ackreq - check if acknowledgment request bit is set
 * @fc: frame control bytes in little-endian byteorder
 */
static inline bool ieee802154_is_ackreq(__le16 fc)
{
	return fc & cpu_to_le16(IEEE802154_FCTL_ACKREQ);
}

255 256 257 258 259 260 261 262 263
/**
 * ieee802154_is_intra_pan - check if intra pan id communication
 * @fc: frame control bytes in little-endian byteorder
 */
static inline bool ieee802154_is_intra_pan(__le16 fc)
{
	return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN);
}

264 265
/**
 * ieee802154_is_valid_psdu_len - check if psdu len is valid
266 267 268 269 270 271
 * available lengths:
 *	0-4	Reserved
 *	5	MPDU (Acknowledgment)
 *	6-8	Reserved
 *	9-127	MPDU
 *
272 273
 * @len: psdu len with (MHR + payload + MFR)
 */
274
static inline bool ieee802154_is_valid_psdu_len(u8 len)
275
{
276 277
	return (len == IEEE802154_ACK_PSDU_LEN ||
		(len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU));
278
}
279

280
/**
281
 * ieee802154_is_valid_extended_unicast_addr - check if extended addr is valid
282 283
 * @addr: extended addr to check
 */
284
static inline bool ieee802154_is_valid_extended_unicast_addr(__le64 addr)
285
{
286 287
	/* Bail out if the address is all zero, or if the group
	 * address bit is set.
288
	 */
289
	return ((addr != cpu_to_le64(0x0000000000000000ULL)) &&
290
		!(addr & cpu_to_le64(0x0100000000000000ULL)));
291 292
}

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
/**
 * ieee802154_is_broadcast_short_addr - check if short addr is broadcast
 * @addr: short addr to check
 */
static inline bool ieee802154_is_broadcast_short_addr(__le16 addr)
{
	return (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST));
}

/**
 * ieee802154_is_unspec_short_addr - check if short addr is unspecified
 * @addr: short addr to check
 */
static inline bool ieee802154_is_unspec_short_addr(__le16 addr)
{
	return (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC));
}

/**
 * ieee802154_is_valid_src_short_addr - check if source short address is valid
 * @addr: short addr to check
 */
static inline bool ieee802154_is_valid_src_short_addr(__le16 addr)
{
	return !(ieee802154_is_broadcast_short_addr(addr) ||
		 ieee802154_is_unspec_short_addr(addr));
}

321 322 323 324 325 326 327 328
/**
 * 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);

329 330 331
	/* clear the group bit, and set the locally administered bit */
	((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] &= ~0x01;
	((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] |= 0x02;
332 333
}

334
#endif /* LINUX_IEEE802154_H */