]>
Commit | Line | Data |
---|---|---|
9ec76716 SL |
1 | /* |
2 | * An interface between IEEE802.15.4 device and rest of the kernel. | |
3 | * | |
74a02fcf | 4 | * Copyright (C) 2007-2012 Siemens AG |
9ec76716 SL |
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> | |
74a02fcf | 24 | * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> |
9ec76716 SL |
25 | */ |
26 | ||
27 | #ifndef IEEE802154_NETDEVICE_H | |
28 | #define IEEE802154_NETDEVICE_H | |
29 | ||
1cd829c8 | 30 | #include <net/af_ieee802154.h> |
31 | ||
46ef0eb3 PB |
32 | struct ieee802154_addr { |
33 | u8 mode; | |
34 | __le16 pan_id; | |
35 | union { | |
36 | __le16 short_addr; | |
37 | __le64 extended_addr; | |
38 | }; | |
39 | }; | |
40 | ||
41 | static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1, | |
42 | const struct ieee802154_addr *a2) | |
43 | { | |
44 | if (a1->pan_id != a2->pan_id || a1->mode != a2->mode) | |
45 | return false; | |
46 | ||
47 | if ((a1->mode == IEEE802154_ADDR_LONG && | |
48 | a1->extended_addr != a2->extended_addr) || | |
49 | (a1->mode == IEEE802154_ADDR_SHORT && | |
50 | a1->short_addr != a2->short_addr)) | |
51 | return false; | |
52 | ||
53 | return true; | |
54 | } | |
55 | ||
56 | static inline __le64 ieee802154_devaddr_from_raw(const void *raw) | |
57 | { | |
58 | u64 temp; | |
59 | ||
60 | memcpy(&temp, raw, IEEE802154_ADDR_LEN); | |
61 | return (__force __le64)swab64(temp); | |
62 | } | |
63 | ||
64 | static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr) | |
65 | { | |
66 | u64 temp = swab64((__force u64)addr); | |
67 | ||
68 | memcpy(raw, &temp, IEEE802154_ADDR_LEN); | |
69 | } | |
70 | ||
71 | static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a, | |
72 | const struct ieee802154_addr_sa *sa) | |
73 | { | |
74 | a->mode = sa->addr_type; | |
75 | a->pan_id = cpu_to_le16(sa->pan_id); | |
76 | ||
77 | switch (a->mode) { | |
78 | case IEEE802154_ADDR_SHORT: | |
79 | a->short_addr = cpu_to_le16(sa->short_addr); | |
80 | break; | |
81 | case IEEE802154_ADDR_LONG: | |
82 | a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr); | |
83 | break; | |
84 | } | |
85 | } | |
86 | ||
87 | static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa, | |
88 | const struct ieee802154_addr *a) | |
89 | { | |
90 | sa->addr_type = a->mode; | |
91 | sa->pan_id = le16_to_cpu(a->pan_id); | |
92 | ||
93 | switch (a->mode) { | |
94 | case IEEE802154_ADDR_SHORT: | |
95 | sa->short_addr = le16_to_cpu(a->short_addr); | |
96 | break; | |
97 | case IEEE802154_ADDR_LONG: | |
98 | ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr); | |
99 | break; | |
100 | } | |
101 | } | |
102 | ||
103 | ||
89745c9c AA |
104 | struct ieee802154_frag_info { |
105 | __be16 d_tag; | |
106 | u16 d_size; | |
107 | u8 d_offset; | |
108 | }; | |
109 | ||
9ec76716 SL |
110 | /* |
111 | * A control block of skb passed between the ARPHRD_IEEE802154 device | |
112 | * and other stack parts. | |
113 | */ | |
114 | struct ieee802154_mac_cb { | |
115 | u8 lqi; | |
376b7bd3 PB |
116 | struct ieee802154_addr_sa sa; |
117 | struct ieee802154_addr_sa da; | |
9ec76716 SL |
118 | u8 flags; |
119 | u8 seq; | |
89745c9c | 120 | struct ieee802154_frag_info frag_info; |
9ec76716 SL |
121 | }; |
122 | ||
123 | static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb) | |
124 | { | |
125 | return (struct ieee802154_mac_cb *)skb->cb; | |
126 | } | |
127 | ||
128 | #define MAC_CB_FLAG_TYPEMASK ((1 << 3) - 1) | |
129 | ||
130 | #define MAC_CB_FLAG_ACKREQ (1 << 3) | |
131 | #define MAC_CB_FLAG_SECEN (1 << 4) | |
132 | #define MAC_CB_FLAG_INTRAPAN (1 << 5) | |
133 | ||
134 | static inline int mac_cb_is_ackreq(struct sk_buff *skb) | |
135 | { | |
136 | return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ; | |
137 | } | |
138 | ||
139 | static inline int mac_cb_is_secen(struct sk_buff *skb) | |
140 | { | |
141 | return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN; | |
142 | } | |
143 | ||
144 | static inline int mac_cb_is_intrapan(struct sk_buff *skb) | |
145 | { | |
146 | return mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN; | |
147 | } | |
148 | ||
149 | static inline int mac_cb_type(struct sk_buff *skb) | |
150 | { | |
151 | return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK; | |
152 | } | |
153 | ||
154 | #define IEEE802154_MAC_SCAN_ED 0 | |
155 | #define IEEE802154_MAC_SCAN_ACTIVE 1 | |
156 | #define IEEE802154_MAC_SCAN_PASSIVE 2 | |
157 | #define IEEE802154_MAC_SCAN_ORPHAN 3 | |
158 | ||
42723448 | 159 | struct wpan_phy; |
9ec76716 SL |
160 | /* |
161 | * This should be located at net_device->ml_priv | |
42723448 DES |
162 | * |
163 | * get_phy should increment the reference counting on returned phy. | |
164 | * Use wpan_wpy_put to put that reference. | |
9ec76716 SL |
165 | */ |
166 | struct ieee802154_mlme_ops { | |
56aa091d WA |
167 | /* The following fields are optional (can be NULL). */ |
168 | ||
9ec76716 | 169 | int (*assoc_req)(struct net_device *dev, |
376b7bd3 | 170 | struct ieee802154_addr_sa *addr, |
16eea493 | 171 | u8 channel, u8 page, u8 cap); |
9ec76716 | 172 | int (*assoc_resp)(struct net_device *dev, |
376b7bd3 | 173 | struct ieee802154_addr_sa *addr, |
b70ab2e8 | 174 | __le16 short_addr, u8 status); |
9ec76716 | 175 | int (*disassoc_req)(struct net_device *dev, |
376b7bd3 | 176 | struct ieee802154_addr_sa *addr, |
9ec76716 SL |
177 | u8 reason); |
178 | int (*start_req)(struct net_device *dev, | |
376b7bd3 | 179 | struct ieee802154_addr_sa *addr, |
16eea493 | 180 | u8 channel, u8 page, u8 bcn_ord, u8 sf_ord, |
9ec76716 SL |
181 | u8 pan_coord, u8 blx, u8 coord_realign); |
182 | int (*scan_req)(struct net_device *dev, | |
16eea493 | 183 | u8 type, u32 channels, u8 page, u8 duration); |
9ec76716 | 184 | |
56aa091d WA |
185 | /* The fields below are required. */ |
186 | ||
42723448 DES |
187 | struct wpan_phy *(*get_phy)(const struct net_device *dev); |
188 | ||
9ec76716 SL |
189 | /* |
190 | * FIXME: these should become the part of PIB/MIB interface. | |
191 | * However we still don't have IB interface of any kind | |
192 | */ | |
b70ab2e8 PB |
193 | __le16 (*get_pan_id)(const struct net_device *dev); |
194 | __le16 (*get_short_addr)(const struct net_device *dev); | |
a9966b58 | 195 | u8 (*get_dsn)(const struct net_device *dev); |
9ec76716 SL |
196 | }; |
197 | ||
74a02fcf | 198 | /* The IEEE 802.15.4 standard defines 2 type of the devices: |
199 | * - FFD - full functionality device | |
200 | * - RFD - reduce functionality device | |
201 | * | |
202 | * So 2 sets of mlme operations are needed | |
203 | */ | |
204 | struct ieee802154_reduced_mlme_ops { | |
205 | struct wpan_phy *(*get_phy)(const struct net_device *dev); | |
206 | }; | |
207 | ||
208 | static inline struct ieee802154_mlme_ops * | |
209 | ieee802154_mlme_ops(const struct net_device *dev) | |
9ec76716 SL |
210 | { |
211 | return dev->ml_priv; | |
212 | } | |
213 | ||
74a02fcf | 214 | static inline struct ieee802154_reduced_mlme_ops * |
215 | ieee802154_reduced_mlme_ops(const struct net_device *dev) | |
216 | { | |
217 | return dev->ml_priv; | |
218 | } | |
9ec76716 | 219 | |
74a02fcf | 220 | #endif |