Skip to content

Commit e6da340

Browse files
Hante Meulemanlinvjw
authored andcommitted
brcmfmac: Add handling of receiving P2P action frames.
Once wpa_supplicant has registered for P2P action frames all received action frames for the device are passed up to cfg80211. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
1 parent a0f0795 commit e6da340

File tree

3 files changed

+350
-0
lines changed

3 files changed

+350
-0
lines changed

drivers/net/wireless/brcm80211/brcmfmac/p2p.c

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,38 @@
4848

4949
#define BRCMF_SCB_TIMEOUT_VALUE 20
5050

51+
#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */
52+
#define P2P_PUB_AF_CATEGORY 0x04
53+
#define P2P_PUB_AF_ACTION 0x09
54+
#define P2P_AF_CATEGORY 0x7f
55+
#define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */
56+
#define P2P_OUI_LEN 3 /* P2P OUI length */
57+
58+
/* WiFi P2P Public Action Frame OUI Subtypes */
59+
#define P2P_PAF_GON_REQ 0 /* Group Owner Negotiation Req */
60+
#define P2P_PAF_GON_RSP 1 /* Group Owner Negotiation Rsp */
61+
#define P2P_PAF_GON_CONF 2 /* Group Owner Negotiation Confirm */
62+
#define P2P_PAF_INVITE_REQ 3 /* P2P Invitation Request */
63+
#define P2P_PAF_INVITE_RSP 4 /* P2P Invitation Response */
64+
#define P2P_PAF_DEVDIS_REQ 5 /* Device Discoverability Request */
65+
#define P2P_PAF_DEVDIS_RSP 6 /* Device Discoverability Response */
66+
#define P2P_PAF_PROVDIS_REQ 7 /* Provision Discovery Request */
67+
#define P2P_PAF_PROVDIS_RSP 8 /* Provision Discovery Response */
68+
#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */
69+
70+
/* WiFi P2P Action Frame OUI Subtypes */
71+
#define P2P_AF_NOTICE_OF_ABSENCE 0 /* Notice of Absence */
72+
#define P2P_AF_PRESENCE_REQ 1 /* P2P Presence Request */
73+
#define P2P_AF_PRESENCE_RSP 2 /* P2P Presence Response */
74+
#define P2P_AF_GO_DISC_REQ 3 /* GO Discoverability Request */
75+
76+
/* P2P Service Discovery related */
77+
#define P2PSD_ACTION_CATEGORY 0x04 /* Public action frame */
78+
#define P2PSD_ACTION_ID_GAS_IREQ 0x0a /* GAS Initial Request AF */
79+
#define P2PSD_ACTION_ID_GAS_IRESP 0x0b /* GAS Initial Response AF */
80+
#define P2PSD_ACTION_ID_GAS_CREQ 0x0c /* GAS Comback Request AF */
81+
#define P2PSD_ACTION_ID_GAS_CRESP 0x0d /* GAS Comback Response AF */
82+
5183
/**
5284
* struct brcmf_p2p_disc_st_le - set discovery state in firmware.
5385
*
@@ -91,6 +123,261 @@ struct brcmf_p2p_scan_le {
91123
};
92124
};
93125

126+
/**
127+
* struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame
128+
*
129+
* @category: P2P_PUB_AF_CATEGORY
130+
* @action: P2P_PUB_AF_ACTION
131+
* @oui[3]: P2P_OUI
132+
* @oui_type: OUI type - P2P_VER
133+
* @subtype: OUI subtype - P2P_TYPE_*
134+
* @dialog_token: nonzero, identifies req/rsp transaction
135+
* @elts[1]: Variable length information elements.
136+
*/
137+
struct brcmf_p2p_pub_act_frame {
138+
u8 category;
139+
u8 action;
140+
u8 oui[3];
141+
u8 oui_type;
142+
u8 subtype;
143+
u8 dialog_token;
144+
u8 elts[1];
145+
};
146+
147+
/**
148+
* struct brcmf_p2p_action_frame - WiFi P2P Action Frame
149+
*
150+
* @category: P2P_AF_CATEGORY
151+
* @OUI[3]: OUI - P2P_OUI
152+
* @type: OUI Type - P2P_VER
153+
* @subtype: OUI Subtype - P2P_AF_*
154+
* @dialog_token: nonzero, identifies req/resp tranaction
155+
* @elts[1]: Variable length information elements.
156+
*/
157+
struct brcmf_p2p_action_frame {
158+
u8 category;
159+
u8 oui[3];
160+
u8 type;
161+
u8 subtype;
162+
u8 dialog_token;
163+
u8 elts[1];
164+
};
165+
166+
/**
167+
* struct brcmf_p2psd_gas_pub_act_frame - Wi-Fi GAS Public Action Frame
168+
*
169+
* @category: 0x04 Public Action Frame
170+
* @action: 0x6c Advertisement Protocol
171+
* @dialog_token: nonzero, identifies req/rsp transaction
172+
* @query_data[1]: Query Data. SD gas ireq SD gas iresp
173+
*/
174+
struct brcmf_p2psd_gas_pub_act_frame {
175+
u8 category;
176+
u8 action;
177+
u8 dialog_token;
178+
u8 query_data[1];
179+
};
180+
181+
182+
/**
183+
* brcmf_p2p_is_pub_action() - true if p2p public type frame.
184+
*
185+
* @frame: action frame data.
186+
* @frame_len: length of action frame data.
187+
*
188+
* Determine if action frame is p2p public action type
189+
*/
190+
static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len)
191+
{
192+
struct brcmf_p2p_pub_act_frame *pact_frm;
193+
194+
if (frame == NULL)
195+
return false;
196+
197+
pact_frm = (struct brcmf_p2p_pub_act_frame *)frame;
198+
if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1)
199+
return false;
200+
201+
if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
202+
pact_frm->action == P2P_PUB_AF_ACTION &&
203+
pact_frm->oui_type == P2P_VER &&
204+
memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
205+
return true;
206+
207+
return false;
208+
}
209+
210+
/**
211+
* brcmf_p2p_is_p2p_action() - true if p2p action type frame.
212+
*
213+
* @frame: action frame data.
214+
* @frame_len: length of action frame data.
215+
*
216+
* Determine if action frame is p2p action type
217+
*/
218+
static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len)
219+
{
220+
struct brcmf_p2p_action_frame *act_frm;
221+
222+
if (frame == NULL)
223+
return false;
224+
225+
act_frm = (struct brcmf_p2p_action_frame *)frame;
226+
if (frame_len < sizeof(struct brcmf_p2p_action_frame) - 1)
227+
return false;
228+
229+
if (act_frm->category == P2P_AF_CATEGORY &&
230+
act_frm->type == P2P_VER &&
231+
memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
232+
return true;
233+
234+
return false;
235+
}
236+
237+
/**
238+
* brcmf_p2p_is_gas_action() - true if p2p gas action type frame.
239+
*
240+
* @frame: action frame data.
241+
* @frame_len: length of action frame data.
242+
*
243+
* Determine if action frame is p2p gas action type
244+
*/
245+
static bool brcmf_p2p_is_gas_action(void *frame, u32 frame_len)
246+
{
247+
struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
248+
249+
if (frame == NULL)
250+
return false;
251+
252+
sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame;
253+
if (frame_len < sizeof(struct brcmf_p2psd_gas_pub_act_frame) - 1)
254+
return false;
255+
256+
if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
257+
return false;
258+
259+
if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
260+
sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
261+
sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
262+
sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
263+
return true;
264+
265+
return false;
266+
}
267+
268+
/**
269+
* brcmf_p2p_print_actframe() - debug print routine.
270+
*
271+
* @tx: Received or to be transmitted
272+
* @frame: action frame data.
273+
* @frame_len: length of action frame data.
274+
*
275+
* Print information about the p2p action frame
276+
*/
277+
static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
278+
{
279+
struct brcmf_p2p_pub_act_frame *pact_frm;
280+
struct brcmf_p2p_action_frame *act_frm;
281+
struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
282+
283+
if (!frame || frame_len <= 2)
284+
return;
285+
286+
if (brcmf_p2p_is_pub_action(frame, frame_len)) {
287+
pact_frm = (struct brcmf_p2p_pub_act_frame *)frame;
288+
switch (pact_frm->subtype) {
289+
case P2P_PAF_GON_REQ:
290+
brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Req Frame\n",
291+
(tx) ? "TX" : "RX");
292+
break;
293+
case P2P_PAF_GON_RSP:
294+
brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Rsp Frame\n",
295+
(tx) ? "TX" : "RX");
296+
break;
297+
case P2P_PAF_GON_CONF:
298+
brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Confirm Frame\n",
299+
(tx) ? "TX" : "RX");
300+
break;
301+
case P2P_PAF_INVITE_REQ:
302+
brcmf_dbg(TRACE, "%s P2P Invitation Request Frame\n",
303+
(tx) ? "TX" : "RX");
304+
break;
305+
case P2P_PAF_INVITE_RSP:
306+
brcmf_dbg(TRACE, "%s P2P Invitation Response Frame\n",
307+
(tx) ? "TX" : "RX");
308+
break;
309+
case P2P_PAF_DEVDIS_REQ:
310+
brcmf_dbg(TRACE, "%s P2P Device Discoverability Request Frame\n",
311+
(tx) ? "TX" : "RX");
312+
break;
313+
case P2P_PAF_DEVDIS_RSP:
314+
brcmf_dbg(TRACE, "%s P2P Device Discoverability Response Frame\n",
315+
(tx) ? "TX" : "RX");
316+
break;
317+
case P2P_PAF_PROVDIS_REQ:
318+
brcmf_dbg(TRACE, "%s P2P Provision Discovery Request Frame\n",
319+
(tx) ? "TX" : "RX");
320+
break;
321+
case P2P_PAF_PROVDIS_RSP:
322+
brcmf_dbg(TRACE, "%s P2P Provision Discovery Response Frame\n",
323+
(tx) ? "TX" : "RX");
324+
break;
325+
default:
326+
brcmf_dbg(TRACE, "%s Unknown P2P Public Action Frame\n",
327+
(tx) ? "TX" : "RX");
328+
break;
329+
}
330+
} else if (brcmf_p2p_is_p2p_action(frame, frame_len)) {
331+
act_frm = (struct brcmf_p2p_action_frame *)frame;
332+
switch (act_frm->subtype) {
333+
case P2P_AF_NOTICE_OF_ABSENCE:
334+
brcmf_dbg(TRACE, "%s P2P Notice of Absence Frame\n",
335+
(tx) ? "TX" : "RX");
336+
break;
337+
case P2P_AF_PRESENCE_REQ:
338+
brcmf_dbg(TRACE, "%s P2P Presence Request Frame\n",
339+
(tx) ? "TX" : "RX");
340+
break;
341+
case P2P_AF_PRESENCE_RSP:
342+
brcmf_dbg(TRACE, "%s P2P Presence Response Frame\n",
343+
(tx) ? "TX" : "RX");
344+
break;
345+
case P2P_AF_GO_DISC_REQ:
346+
brcmf_dbg(TRACE, "%s P2P Discoverability Request Frame\n",
347+
(tx) ? "TX" : "RX");
348+
break;
349+
default:
350+
brcmf_dbg(TRACE, "%s Unknown P2P Action Frame\n",
351+
(tx) ? "TX" : "RX");
352+
}
353+
354+
} else if (brcmf_p2p_is_gas_action(frame, frame_len)) {
355+
sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame;
356+
switch (sd_act_frm->action) {
357+
case P2PSD_ACTION_ID_GAS_IREQ:
358+
brcmf_dbg(TRACE, "%s P2P GAS Initial Request\n",
359+
(tx) ? "TX" : "RX");
360+
break;
361+
case P2PSD_ACTION_ID_GAS_IRESP:
362+
brcmf_dbg(TRACE, "%s P2P GAS Initial Response\n",
363+
(tx) ? "TX" : "RX");
364+
break;
365+
case P2PSD_ACTION_ID_GAS_CREQ:
366+
brcmf_dbg(TRACE, "%s P2P GAS Comback Request\n",
367+
(tx) ? "TX" : "RX");
368+
break;
369+
case P2PSD_ACTION_ID_GAS_CRESP:
370+
brcmf_dbg(TRACE, "%s P2P GAS Comback Response\n",
371+
(tx) ? "TX" : "RX");
372+
break;
373+
default:
374+
brcmf_dbg(TRACE, "%s Unknown P2P GAS Frame\n",
375+
(tx) ? "TX" : "RX");
376+
break;
377+
}
378+
}
379+
}
380+
94381
/**
95382
* brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
96383
*
@@ -686,6 +973,64 @@ void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp)
686973
}
687974

688975

976+
/**
977+
* brcmf_p2p_notify_action_frame_rx() - received action frame.
978+
*
979+
* @ifp: interfac control.
980+
* @e: event message. Not used, to make it usable for fweh event dispatcher.
981+
* @data: payload of message, containing action frame data.
982+
*
983+
*/
984+
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
985+
const struct brcmf_event_msg *e,
986+
void *data)
987+
{
988+
struct wireless_dev *wdev;
989+
u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data);
990+
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
991+
u16 chanspec = be16_to_cpu(rxframe->chanspec);
992+
struct ieee80211_mgmt *mgmt_frame;
993+
s32 err;
994+
s32 freq;
995+
u16 mgmt_type;
996+
997+
/* Check if wpa_supplicant has registered for this frame */
998+
brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg);
999+
mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4;
1000+
if ((ifp->vif->mgmt_rx_reg & BIT(mgmt_type)) == 0)
1001+
return 0;
1002+
1003+
brcmf_p2p_print_actframe(false, (u8 *)(rxframe + 1), mgmt_frame_len);
1004+
1005+
mgmt_frame = kzalloc(offsetof(struct ieee80211_mgmt, u) +
1006+
mgmt_frame_len, GFP_KERNEL);
1007+
if (!mgmt_frame) {
1008+
brcmf_err("No memory available for action frame\n");
1009+
return -ENOMEM;
1010+
}
1011+
memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN);
1012+
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid,
1013+
ETH_ALEN);
1014+
if (err < 0)
1015+
brcmf_err("BRCMF_C_GET_BSSID error %d\n", err);
1016+
memcpy(mgmt_frame->sa, e->addr, ETH_ALEN);
1017+
mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION);
1018+
memcpy(&mgmt_frame->u, (u8 *)(rxframe + 1), mgmt_frame_len);
1019+
mgmt_frame_len += offsetof(struct ieee80211_mgmt, u);
1020+
1021+
freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
1022+
CHSPEC_IS2G(chanspec) ?
1023+
IEEE80211_BAND_2GHZ :
1024+
IEEE80211_BAND_5GHZ);
1025+
wdev = ifp->ndev->ieee80211_ptr;
1026+
cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
1027+
GFP_ATOMIC);
1028+
1029+
kfree(mgmt_frame);
1030+
return 0;
1031+
}
1032+
1033+
6891034
/**
6901035
* brcmf_p2p_attach() - attach for P2P.
6911036
*

drivers/net/wireless/brcm80211/brcmfmac/p2p.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,8 @@ int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
123123
const struct brcmf_event_msg *e,
124124
void *data);
125125
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
126+
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
127+
const struct brcmf_event_msg *e,
128+
void *data);
126129

127130
#endif /* WL_CFGP2P_H_ */

drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4701,6 +4701,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
47014701
brcmf_notify_rx_mgmt_p2p_probereq);
47024702
brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE,
47034703
brcmf_p2p_notify_listen_complete);
4704+
brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,
4705+
brcmf_p2p_notify_action_frame_rx);
47044706
}
47054707

47064708
static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)

0 commit comments

Comments
 (0)