Commit | Line | Data |
---|---|---|
5c36b99a AS |
1 | /* |
2 | * Copyright (c) 2012 Broadcom Corporation | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | ||
18 | #ifndef FWEH_H_ | |
19 | #define FWEH_H_ | |
20 | ||
b6f06f6e | 21 | #include <asm/unaligned.h> |
5c36b99a AS |
22 | #include <linux/skbuff.h> |
23 | #include <linux/if_ether.h> | |
24 | #include <linux/if.h> | |
25 | ||
26 | /* formward declarations */ | |
27 | struct brcmf_pub; | |
28 | struct brcmf_if; | |
29 | struct brcmf_cfg80211_info; | |
30 | struct brcmf_event; | |
31 | ||
dc5cbdfd AS |
32 | /* list of firmware events */ |
33 | #define BRCMF_FWEH_EVENT_ENUM_DEFLIST \ | |
34 | BRCMF_ENUM_DEF(SET_SSID, 0) \ | |
35 | BRCMF_ENUM_DEF(JOIN, 1) \ | |
36 | BRCMF_ENUM_DEF(START, 2) \ | |
37 | BRCMF_ENUM_DEF(AUTH, 3) \ | |
38 | BRCMF_ENUM_DEF(AUTH_IND, 4) \ | |
39 | BRCMF_ENUM_DEF(DEAUTH, 5) \ | |
40 | BRCMF_ENUM_DEF(DEAUTH_IND, 6) \ | |
41 | BRCMF_ENUM_DEF(ASSOC, 7) \ | |
42 | BRCMF_ENUM_DEF(ASSOC_IND, 8) \ | |
43 | BRCMF_ENUM_DEF(REASSOC, 9) \ | |
44 | BRCMF_ENUM_DEF(REASSOC_IND, 10) \ | |
45 | BRCMF_ENUM_DEF(DISASSOC, 11) \ | |
46 | BRCMF_ENUM_DEF(DISASSOC_IND, 12) \ | |
47 | BRCMF_ENUM_DEF(QUIET_START, 13) \ | |
48 | BRCMF_ENUM_DEF(QUIET_END, 14) \ | |
49 | BRCMF_ENUM_DEF(BEACON_RX, 15) \ | |
50 | BRCMF_ENUM_DEF(LINK, 16) \ | |
51 | BRCMF_ENUM_DEF(MIC_ERROR, 17) \ | |
52 | BRCMF_ENUM_DEF(NDIS_LINK, 18) \ | |
53 | BRCMF_ENUM_DEF(ROAM, 19) \ | |
54 | BRCMF_ENUM_DEF(TXFAIL, 20) \ | |
55 | BRCMF_ENUM_DEF(PMKID_CACHE, 21) \ | |
56 | BRCMF_ENUM_DEF(RETROGRADE_TSF, 22) \ | |
57 | BRCMF_ENUM_DEF(PRUNE, 23) \ | |
58 | BRCMF_ENUM_DEF(AUTOAUTH, 24) \ | |
59 | BRCMF_ENUM_DEF(EAPOL_MSG, 25) \ | |
60 | BRCMF_ENUM_DEF(SCAN_COMPLETE, 26) \ | |
61 | BRCMF_ENUM_DEF(ADDTS_IND, 27) \ | |
62 | BRCMF_ENUM_DEF(DELTS_IND, 28) \ | |
63 | BRCMF_ENUM_DEF(BCNSENT_IND, 29) \ | |
64 | BRCMF_ENUM_DEF(BCNRX_MSG, 30) \ | |
65 | BRCMF_ENUM_DEF(BCNLOST_MSG, 31) \ | |
66 | BRCMF_ENUM_DEF(ROAM_PREP, 32) \ | |
67 | BRCMF_ENUM_DEF(PFN_NET_FOUND, 33) \ | |
68 | BRCMF_ENUM_DEF(PFN_NET_LOST, 34) \ | |
69 | BRCMF_ENUM_DEF(RESET_COMPLETE, 35) \ | |
70 | BRCMF_ENUM_DEF(JOIN_START, 36) \ | |
71 | BRCMF_ENUM_DEF(ROAM_START, 37) \ | |
72 | BRCMF_ENUM_DEF(ASSOC_START, 38) \ | |
73 | BRCMF_ENUM_DEF(IBSS_ASSOC, 39) \ | |
74 | BRCMF_ENUM_DEF(RADIO, 40) \ | |
75 | BRCMF_ENUM_DEF(PSM_WATCHDOG, 41) \ | |
76 | BRCMF_ENUM_DEF(PROBREQ_MSG, 44) \ | |
77 | BRCMF_ENUM_DEF(SCAN_CONFIRM_IND, 45) \ | |
78 | BRCMF_ENUM_DEF(PSK_SUP, 46) \ | |
79 | BRCMF_ENUM_DEF(COUNTRY_CODE_CHANGED, 47) \ | |
80 | BRCMF_ENUM_DEF(EXCEEDED_MEDIUM_TIME, 48) \ | |
81 | BRCMF_ENUM_DEF(ICV_ERROR, 49) \ | |
82 | BRCMF_ENUM_DEF(UNICAST_DECODE_ERROR, 50) \ | |
83 | BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \ | |
84 | BRCMF_ENUM_DEF(TRACE, 52) \ | |
85 | BRCMF_ENUM_DEF(IF, 54) \ | |
0de8aace | 86 | BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \ |
dc5cbdfd AS |
87 | BRCMF_ENUM_DEF(RSSI, 56) \ |
88 | BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \ | |
89 | BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \ | |
90 | BRCMF_ENUM_DEF(ACTION_FRAME, 59) \ | |
91 | BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \ | |
92 | BRCMF_ENUM_DEF(PRE_ASSOC_IND, 61) \ | |
93 | BRCMF_ENUM_DEF(PRE_REASSOC_IND, 62) \ | |
94 | BRCMF_ENUM_DEF(CHANNEL_ADOPTED, 63) \ | |
95 | BRCMF_ENUM_DEF(AP_STARTED, 64) \ | |
96 | BRCMF_ENUM_DEF(DFS_AP_STOP, 65) \ | |
97 | BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \ | |
98 | BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \ | |
99 | BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \ | |
0de8aace HM |
100 | BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \ |
101 | BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \ | |
dc5cbdfd | 102 | BRCMF_ENUM_DEF(DCS_REQUEST, 73) \ |
0de8aace | 103 | BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ |
7d747037 | 104 | BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ |
4cd0ea45 FL |
105 | BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \ |
106 | BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128) | |
dc5cbdfd AS |
107 | |
108 | #define BRCMF_ENUM_DEF(id, val) \ | |
109 | BRCMF_E_##id = (val), | |
110 | ||
5c36b99a AS |
111 | /* firmware event codes sent by the dongle */ |
112 | enum brcmf_fweh_event_code { | |
dc5cbdfd | 113 | BRCMF_FWEH_EVENT_ENUM_DEFLIST |
5c36b99a AS |
114 | BRCMF_E_LAST |
115 | }; | |
dc5cbdfd | 116 | #undef BRCMF_ENUM_DEF |
5c36b99a | 117 | |
5af47fb3 | 118 | #define BRCMF_EVENTING_MASK_LEN DIV_ROUND_UP(BRCMF_E_LAST, 8) |
4cd0ea45 | 119 | |
5c36b99a AS |
120 | /* flags field values in struct brcmf_event_msg */ |
121 | #define BRCMF_EVENT_MSG_LINK 0x01 | |
122 | #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 | |
123 | #define BRCMF_EVENT_MSG_GROUP 0x04 | |
124 | ||
125 | /** | |
126 | * definitions for event packet validation. | |
127 | */ | |
128 | #define BRCMF_EVENT_OUI_OFFSET 19 | |
129 | #define BRCM_OUI "\x00\x10\x18" | |
130 | #define DOT11_OUI_LEN 3 | |
131 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 | |
132 | ||
133 | ||
134 | /** | |
135 | * struct brcmf_event_msg - firmware event message. | |
136 | * | |
137 | * @version: version information. | |
138 | * @flags: event flags. | |
139 | * @event_code: firmware event code. | |
140 | * @status: status information. | |
141 | * @reason: reason code. | |
142 | * @auth_type: authentication type. | |
143 | * @datalen: lenght of event data buffer. | |
144 | * @addr: ether address. | |
145 | * @ifname: interface name. | |
146 | * @ifidx: interface index. | |
147 | * @bsscfgidx: bsscfg index. | |
148 | */ | |
149 | struct brcmf_event_msg { | |
150 | u16 version; | |
151 | u16 flags; | |
152 | u32 event_code; | |
153 | u32 status; | |
154 | u32 reason; | |
155 | s32 auth_type; | |
156 | u32 datalen; | |
157 | u8 addr[ETH_ALEN]; | |
158 | char ifname[IFNAMSIZ]; | |
159 | u8 ifidx; | |
160 | u8 bsscfgidx; | |
161 | }; | |
162 | ||
163 | typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, | |
164 | const struct brcmf_event_msg *evtmsg, | |
165 | void *data); | |
166 | ||
167 | /** | |
168 | * struct brcmf_fweh_info - firmware event handling information. | |
169 | * | |
170 | * @event_work: event worker. | |
171 | * @evt_q_lock: lock for event queue protection. | |
172 | * @event_q: event queue. | |
173 | * @evt_handler: registered event handlers. | |
174 | */ | |
175 | struct brcmf_fweh_info { | |
176 | struct work_struct event_work; | |
f241b244 | 177 | spinlock_t evt_q_lock; |
5c36b99a AS |
178 | struct list_head event_q; |
179 | int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp, | |
180 | const struct brcmf_event_msg *evtmsg, | |
181 | void *data); | |
182 | }; | |
183 | ||
184 | void brcmf_fweh_attach(struct brcmf_pub *drvr); | |
185 | void brcmf_fweh_detach(struct brcmf_pub *drvr); | |
186 | int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code, | |
187 | int (*handler)(struct brcmf_if *ifp, | |
188 | const struct brcmf_event_msg *evtmsg, | |
189 | void *data)); | |
190 | void brcmf_fweh_unregister(struct brcmf_pub *drvr, | |
191 | enum brcmf_fweh_event_code code); | |
192 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); | |
193 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |
deb09280 | 194 | struct brcmf_event *event_packet); |
5c36b99a AS |
195 | |
196 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, | |
deb09280 | 197 | struct sk_buff *skb) |
5c36b99a AS |
198 | { |
199 | struct brcmf_event *event_packet; | |
200 | u8 *data; | |
201 | u16 usr_stype; | |
202 | ||
203 | /* only process events when protocol matches */ | |
204 | if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL)) | |
205 | return; | |
206 | ||
207 | /* check for BRCM oui match */ | |
208 | event_packet = (struct brcmf_event *)skb_mac_header(skb); | |
209 | data = (u8 *)event_packet; | |
210 | data += BRCMF_EVENT_OUI_OFFSET; | |
211 | if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN)) | |
212 | return; | |
213 | ||
214 | /* final match on usr_subtype */ | |
215 | data += DOT11_OUI_LEN; | |
216 | usr_stype = get_unaligned_be16(data); | |
217 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) | |
218 | return; | |
219 | ||
deb09280 | 220 | brcmf_fweh_process_event(drvr, event_packet); |
5c36b99a AS |
221 | } |
222 | ||
223 | #endif /* FWEH_H_ */ |