1 /* 2 * An interface between IEEE802.15.4 device and rest of the kernel. 3 * 4 * Copyright (C) 2007-2012 Siemens AG 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Written by: 20 * Pavel Smolenskiy <pavel.smolenskiy@gmail.com> 21 * Maxim Gorbachyov <maxim.gorbachev@siemens.com> 22 * Maxim Osipov <maxim.osipov@siemens.com> 23 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 24 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 25 */ 26 27 #ifndef IEEE802154_NETDEVICE_H 28 #define IEEE802154_NETDEVICE_H 29 30 #include <net/af_ieee802154.h> 31 #include <linux/netdevice.h> 32 #include <linux/skbuff.h> 33 34 struct ieee802154_sechdr { 35 #if defined(__LITTLE_ENDIAN_BITFIELD) 36 u8 level:3, 37 key_id_mode:2, 38 reserved:3; 39 #elif defined(__BIG_ENDIAN_BITFIELD) 40 u8 reserved:3, 41 key_id_mode:2, 42 level:3; 43 #else 44 #error "Please fix <asm/byteorder.h>" 45 #endif 46 u8 key_id; 47 __le32 frame_counter; 48 union { 49 __le32 short_src; 50 __le64 extended_src; 51 }; 52 }; 53 54 struct ieee802154_addr { 55 u8 mode; 56 __le16 pan_id; 57 union { 58 __le16 short_addr; 59 __le64 extended_addr; 60 }; 61 }; 62 63 struct ieee802154_hdr_fc { 64 #if defined(__LITTLE_ENDIAN_BITFIELD) 65 u16 type:3, 66 security_enabled:1, 67 frame_pending:1, 68 ack_request:1, 69 intra_pan:1, 70 reserved:3, 71 dest_addr_mode:2, 72 version:2, 73 source_addr_mode:2; 74 #elif defined(__BIG_ENDIAN_BITFIELD) 75 u16 reserved:1, 76 intra_pan:1, 77 ack_request:1, 78 frame_pending:1, 79 security_enabled:1, 80 type:3, 81 source_addr_mode:2, 82 version:2, 83 dest_addr_mode:2, 84 reserved2:2; 85 #else 86 #error "Please fix <asm/byteorder.h>" 87 #endif 88 }; 89 90 struct ieee802154_hdr { 91 struct ieee802154_hdr_fc fc; 92 u8 seq; 93 struct ieee802154_addr source; 94 struct ieee802154_addr dest; 95 struct ieee802154_sechdr sec; 96 }; 97 98 /* pushes hdr onto the skb. fields of hdr->fc that can be calculated from 99 * the contents of hdr will be, and the actual value of those bits in 100 * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame 101 * version, if SECEN is set. 102 */ 103 int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr); 104 105 /* pulls the entire 802.15.4 header off of the skb, including the security 106 * header, and performs pan id decompression 107 */ 108 int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr); 109 110 /* parses the frame control, sequence number of address fields in a given skb 111 * and stores them into hdr, performing pan id decompression and length checks 112 * to be suitable for use in header_ops.parse 113 */ 114 int ieee802154_hdr_peek_addrs(const struct sk_buff *skb, 115 struct ieee802154_hdr *hdr); 116 117 static inline int ieee802154_hdr_length(struct sk_buff *skb) 118 { 119 struct ieee802154_hdr hdr; 120 int len = ieee802154_hdr_pull(skb, &hdr); 121 122 if (len > 0) 123 skb_push(skb, len); 124 125 return len; 126 } 127 128 static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1, 129 const struct ieee802154_addr *a2) 130 { 131 if (a1->pan_id != a2->pan_id || a1->mode != a2->mode) 132 return false; 133 134 if ((a1->mode == IEEE802154_ADDR_LONG && 135 a1->extended_addr != a2->extended_addr) || 136 (a1->mode == IEEE802154_ADDR_SHORT && 137 a1->short_addr != a2->short_addr)) 138 return false; 139 140 return true; 141 } 142 143 static inline __le64 ieee802154_devaddr_from_raw(const void *raw) 144 { 145 u64 temp; 146 147 memcpy(&temp, raw, IEEE802154_ADDR_LEN); 148 return (__force __le64)swab64(temp); 149 } 150 151 static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr) 152 { 153 u64 temp = swab64((__force u64)addr); 154 155 memcpy(raw, &temp, IEEE802154_ADDR_LEN); 156 } 157 158 static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a, 159 const struct ieee802154_addr_sa *sa) 160 { 161 a->mode = sa->addr_type; 162 a->pan_id = cpu_to_le16(sa->pan_id); 163 164 switch (a->mode) { 165 case IEEE802154_ADDR_SHORT: 166 a->short_addr = cpu_to_le16(sa->short_addr); 167 break; 168 case IEEE802154_ADDR_LONG: 169 a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr); 170 break; 171 } 172 } 173 174 static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa, 175 const struct ieee802154_addr *a) 176 { 177 sa->addr_type = a->mode; 178 sa->pan_id = le16_to_cpu(a->pan_id); 179 180 switch (a->mode) { 181 case IEEE802154_ADDR_SHORT: 182 sa->short_addr = le16_to_cpu(a->short_addr); 183 break; 184 case IEEE802154_ADDR_LONG: 185 ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr); 186 break; 187 } 188 } 189 190 /* 191 * A control block of skb passed between the ARPHRD_IEEE802154 device 192 * and other stack parts. 193 */ 194 struct ieee802154_mac_cb { 195 u8 lqi; 196 u8 flags; 197 u8 seq; 198 struct ieee802154_addr source; 199 struct ieee802154_addr dest; 200 }; 201 202 static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb) 203 { 204 return (struct ieee802154_mac_cb *)skb->cb; 205 } 206 207 #define MAC_CB_FLAG_TYPEMASK ((1 << 3) - 1) 208 209 #define MAC_CB_FLAG_ACKREQ (1 << 3) 210 #define MAC_CB_FLAG_SECEN (1 << 4) 211 212 static inline bool mac_cb_is_ackreq(struct sk_buff *skb) 213 { 214 return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ; 215 } 216 217 static inline bool mac_cb_is_secen(struct sk_buff *skb) 218 { 219 return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN; 220 } 221 222 static inline int mac_cb_type(struct sk_buff *skb) 223 { 224 return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK; 225 } 226 227 #define IEEE802154_MAC_SCAN_ED 0 228 #define IEEE802154_MAC_SCAN_ACTIVE 1 229 #define IEEE802154_MAC_SCAN_PASSIVE 2 230 #define IEEE802154_MAC_SCAN_ORPHAN 3 231 232 struct ieee802154_mac_params { 233 s8 transmit_power; 234 u8 min_be; 235 u8 max_be; 236 u8 csma_retries; 237 s8 frame_retries; 238 239 bool lbt; 240 u8 cca_mode; 241 s32 cca_ed_level; 242 }; 243 244 struct wpan_phy; 245 /* 246 * This should be located at net_device->ml_priv 247 * 248 * get_phy should increment the reference counting on returned phy. 249 * Use wpan_wpy_put to put that reference. 250 */ 251 struct ieee802154_mlme_ops { 252 /* The following fields are optional (can be NULL). */ 253 254 int (*assoc_req)(struct net_device *dev, 255 struct ieee802154_addr *addr, 256 u8 channel, u8 page, u8 cap); 257 int (*assoc_resp)(struct net_device *dev, 258 struct ieee802154_addr *addr, 259 __le16 short_addr, u8 status); 260 int (*disassoc_req)(struct net_device *dev, 261 struct ieee802154_addr *addr, 262 u8 reason); 263 int (*start_req)(struct net_device *dev, 264 struct ieee802154_addr *addr, 265 u8 channel, u8 page, u8 bcn_ord, u8 sf_ord, 266 u8 pan_coord, u8 blx, u8 coord_realign); 267 int (*scan_req)(struct net_device *dev, 268 u8 type, u32 channels, u8 page, u8 duration); 269 270 int (*set_mac_params)(struct net_device *dev, 271 const struct ieee802154_mac_params *params); 272 void (*get_mac_params)(struct net_device *dev, 273 struct ieee802154_mac_params *params); 274 275 /* The fields below are required. */ 276 277 struct wpan_phy *(*get_phy)(const struct net_device *dev); 278 279 /* 280 * FIXME: these should become the part of PIB/MIB interface. 281 * However we still don't have IB interface of any kind 282 */ 283 __le16 (*get_pan_id)(const struct net_device *dev); 284 __le16 (*get_short_addr)(const struct net_device *dev); 285 u8 (*get_dsn)(const struct net_device *dev); 286 }; 287 288 /* The IEEE 802.15.4 standard defines 2 type of the devices: 289 * - FFD - full functionality device 290 * - RFD - reduce functionality device 291 * 292 * So 2 sets of mlme operations are needed 293 */ 294 struct ieee802154_reduced_mlme_ops { 295 struct wpan_phy *(*get_phy)(const struct net_device *dev); 296 }; 297 298 static inline struct ieee802154_mlme_ops * 299 ieee802154_mlme_ops(const struct net_device *dev) 300 { 301 return dev->ml_priv; 302 } 303 304 static inline struct ieee802154_reduced_mlme_ops * 305 ieee802154_reduced_mlme_ops(const struct net_device *dev) 306 { 307 return dev->ml_priv; 308 } 309 310 #endif 311