staging: wilc1000: remove unused preprocessor definition
[deliverable/linux.git] / drivers / staging / wilc1000 / linux_mon.c
CommitLineData
c5c77ba1
JK
1/*!
2 * @file linux_mon.c
3 * @brief File Operations OS wrapper functionality
4 * @author mdaftedar
5 * @sa wilc_wfi_netdevice.h
6 * @date 01 MAR 2012
7 * @version 1.0
8 */
c5c77ba1
JK
9#include "wilc_wfi_cfgoperations.h"
10#include "linux_wlan_common.h"
11#include "wilc_wlan_if.h"
12#include "wilc_wlan.h"
9690df3f 13
c5c77ba1 14#ifdef WILC_AP_EXTERNAL_MLME
c5c77ba1
JK
15
16struct wilc_wfi_radiotap_hdr {
17 struct ieee80211_radiotap_header hdr;
18 u8 rate;
19 /* u32 channel; */
20} __attribute__((packed));
21
22struct wilc_wfi_radiotap_cb_hdr {
23 struct ieee80211_radiotap_header hdr;
24 u8 rate;
25 u8 dump;
26 u16 tx_flags;
27 /* u32 channel; */
28} __attribute__((packed));
29
30extern linux_wlan_t *g_linux_wlan;
31
32static struct net_device *wilc_wfi_mon; /* global monitor netdev */
33
9690df3f 34#if USE_WIRELESS
c5c77ba1
JK
35extern int mac_xmit(struct sk_buff *skb, struct net_device *dev);
36#endif
37
38
63d03e47
GKH
39u8 srcAdd[6];
40u8 bssid[6];
41u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
c5c77ba1
JK
42/**
43 * @brief WILC_WFI_monitor_rx
44 * @details
45 * @param[in]
46 * @return int : Return 0 on Success
47 * @author mdaftedar
48 * @date 12 JUL 2012
49 * @version 1.0
50 */
51
52#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
53#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
54#define IS_MANAGMEMENT 0x100
55#define IS_MANAGMEMENT_CALLBACK 0x080
56#define IS_MGMT_STATUS_SUCCES 0x040
57#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
58
59void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size)
60{
61 uint32_t header, pkt_offset;
62 struct sk_buff *skb = NULL;
63 struct wilc_wfi_radiotap_hdr *hdr;
64 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
65
66 PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n");
67
68 /* struct WILC_WFI_priv *priv = netdev_priv(dev); */
69
70 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
71
72 /* Bug 4601 */
73 if (wilc_wfi_mon == NULL)
74 return;
75
76 if (!netif_running(wilc_wfi_mon)) {
77 PRINT_INFO(HOSTAPD_DBG, "Monitor interface already RUNNING\n");
78 return;
79 }
80
81 /* Get WILC header */
82 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
83
84 /* The packet offset field conain info about what type of managment frame */
85 /* we are dealing with and ack status */
86 pkt_offset = GET_PKT_OFFSET(header);
87
88 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
89
90 /* hostapd callback mgmt frame */
91
92 skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr));
93 if (skb == NULL) {
94 PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
95 return;
96 }
97
98 memcpy(skb_put(skb, size), buff, size);
99
100 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
101 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
102
103 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
104
105 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
106
107 cb_hdr->hdr.it_present = cpu_to_le32(
108 (1 << IEEE80211_RADIOTAP_RATE) |
109 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
110
111 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
112
113 if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
114 /* success */
115 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
116 } else {
117 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
118 }
119
120 } else {
121
122 skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr));
123
124 if (skb == NULL) {
125 PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
126 return;
127 }
128
129 /* skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); */
130 /* if (skb == NULL) */
131 /* return; */
132
133 memcpy(skb_put(skb, size), buff, size);
134 hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
135 memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr));
136 hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
137 /* hdr->hdr.it_pad = 0; */
138 hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr));
139 PRINT_INFO(HOSTAPD_DBG, "Radiotap len %d\n", hdr->hdr.it_len);
140 hdr->hdr.it_present = cpu_to_le32
141 (1 << IEEE80211_RADIOTAP_RATE); /* | */
142 /* (1 << IEEE80211_RADIOTAP_CHANNEL)); */
143 PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present);
144 hdr->rate = 5; /* txrate->bitrate / 5; */
145
146 }
147
148/* if(INFO || if(skb->data[9] == 0x00 || skb->data[9] == 0xb0))
149 * {
150 * for(i=0;i<skb->len;i++)
151 * PRINT_INFO(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,skb->data[i]);
152 * }*/
153
154
155 skb->dev = wilc_wfi_mon;
156 skb_set_mac_header(skb, 0);
157 skb->ip_summed = CHECKSUM_UNNECESSARY;
158 skb->pkt_type = PACKET_OTHERHOST;
159 skb->protocol = htons(ETH_P_802_2);
160 memset(skb->cb, 0, sizeof(skb->cb));
161
162 netif_rx(skb);
163
164
165}
166
167struct tx_complete_mon_data {
168 int size;
169 void *buff;
170};
171
172static void mgmt_tx_complete(void *priv, int status)
173{
174
175 /* struct sk_buff *skb2; */
176 /* struct wilc_wfi_radiotap_cb_hdr *cb_hdr; */
177
178 struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv;
63d03e47 179 u8 *buf = pv_data->buff;
c5c77ba1
JK
180
181
182
183 if (status == 1) {
184 if (INFO || buf[0] == 0x10 || buf[0] == 0xb0)
185 PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
186 } else {
187 PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
188 }
189
190
191/* //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 )
192 * {
193 * skb2 = dev_alloc_skb(pv_data->size+sizeof(struct wilc_wfi_radiotap_cb_hdr));
194 *
195 * memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size);
196 *
197 * cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
198 * memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
199 *
200 * cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
201 *
202 * cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
203 *
204 * cb_hdr->hdr.it_present = cpu_to_le32(
205 * (1 << IEEE80211_RADIOTAP_RATE) |
206 * (1 << IEEE80211_RADIOTAP_TX_FLAGS));
207 *
208 * cb_hdr->rate = 5;//txrate->bitrate / 5;
209 * cb_hdr->tx_flags = 0x0004;
210 *
211 * skb2->dev = wilc_wfi_mon;
212 * skb_set_mac_header(skb2, 0);
213 * skb2->ip_summed = CHECKSUM_UNNECESSARY;
214 * skb2->pkt_type = PACKET_OTHERHOST;
215 * skb2->protocol = htons(ETH_P_802_2);
216 * memset(skb2->cb, 0, sizeof(skb2->cb));
217 *
218 * netif_rx(skb2);
219 * }*/
220
221 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
c5c77ba1
JK
222 kfree(pv_data->buff);
223
224 kfree(pv_data);
c5c77ba1
JK
225}
226static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
227{
c5c77ba1
JK
228 struct tx_complete_mon_data *mgmt_tx = NULL;
229
230 if (dev == NULL) {
231 PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n");
232 return WILC_FAIL;
233 }
c5c77ba1
JK
234
235 netif_stop_queue(dev);
25fe2274 236 mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC);
c5c77ba1
JK
237 if (mgmt_tx == NULL) {
238 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
239 return WILC_FAIL;
240 }
241
30ef5c8b 242 mgmt_tx->buff = kmalloc(len, GFP_ATOMIC);
c5c77ba1
JK
243 if (mgmt_tx->buff == NULL) {
244 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
245 return WILC_FAIL;
246
247 }
248
249 mgmt_tx->size = len;
250
c5c77ba1 251 memcpy(mgmt_tx->buff, buf, len);
c5c77ba1
JK
252 g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, mgmt_tx_complete);
253
254 netif_wake_queue(dev);
255 return 0;
256}
257
258/**
259 * @brief WILC_WFI_mon_xmit
260 * @details
261 * @param[in]
262 * @return int : Return 0 on Success
263 * @author mdaftedar
264 * @date 12 JUL 2012
265 * @version 1.0
266 */
267static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
268 struct net_device *dev)
269{
4e4467fd 270 u32 rtap_len, i, ret = 0;
c5c77ba1
JK
271 struct WILC_WFI_mon_priv *mon_priv;
272
273 struct sk_buff *skb2;
274 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
275
276 /* Bug 4601 */
277 if (wilc_wfi_mon == NULL)
278 return WILC_FAIL;
279
280 /* if(skb->data[3] == 0x10 || skb->data[3] == 0xb0) */
281
282 mon_priv = netdev_priv(wilc_wfi_mon);
283
284 if (mon_priv == NULL) {
285 PRINT_ER("Monitor interface private structure is NULL\n");
286 return WILC_FAIL;
287 }
288
c5c77ba1
JK
289
290 rtap_len = ieee80211_get_radiotap_len(skb->data);
291 if (skb->len < rtap_len) {
292 PRINT_ER("Error in radiotap header\n");
293 return -1;
294 }
295 /* skip the radiotap header */
296 PRINT_INFO(HOSTAPD_DBG, "Radiotap len: %d\n", rtap_len);
297
298 if (INFO) {
299 for (i = 0; i < rtap_len; i++)
300 PRINT_INFO(HOSTAPD_DBG, "Radiotap_hdr[%d] %02x\n", i, skb->data[i]);
301 }
302 /* Skip the ratio tap header */
303 skb_pull(skb, rtap_len);
304
305 if (skb->data[0] == 0xc0)
306 PRINT_INFO(HOSTAPD_DBG, "%x:%x:%x:%x:%x%x\n", skb->data[4], skb->data[5], skb->data[6], skb->data[7], skb->data[8], skb->data[9]);
307
308 if (skb->data[0] == 0xc0 && (!(memcmp(broadcast, &skb->data[4], 6)))) {
309 skb2 = dev_alloc_skb(skb->len + sizeof(struct wilc_wfi_radiotap_cb_hdr));
310
311 memcpy(skb_put(skb2, skb->len), skb->data, skb->len);
312
313 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
314 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
315
316 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
317
318 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
319
320 cb_hdr->hdr.it_present = cpu_to_le32(
321 (1 << IEEE80211_RADIOTAP_RATE) |
322 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
323
324 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
325 cb_hdr->tx_flags = 0x0004;
326
327 skb2->dev = wilc_wfi_mon;
328 skb_set_mac_header(skb2, 0);
329 skb2->ip_summed = CHECKSUM_UNNECESSARY;
330 skb2->pkt_type = PACKET_OTHERHOST;
331 skb2->protocol = htons(ETH_P_802_2);
332 memset(skb2->cb, 0, sizeof(skb2->cb));
333
334 netif_rx(skb2);
335
336 return 0;
337 }
338 skb->dev = mon_priv->real_ndev;
339
340 PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n");
341
342
343
344 /* actual deliver of data is device-specific, and not shown here */
345 PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name);
346 PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name);
347
9690df3f 348 #if USE_WIRELESS
c5c77ba1
JK
349 /* Identify if Ethernet or MAC header (data or mgmt) */
350 memcpy(srcAdd, &skb->data[10], 6);
351 memcpy(bssid, &skb->data[16], 6);
352 /* if source address and bssid fields are equal>>Mac header */
353 /*send it to mgmt frames handler */
354 if (!(memcmp(srcAdd, bssid, 6))) {
355 mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len);
356 dev_kfree_skb(skb);
357 } else
358 ret = mac_xmit(skb, mon_priv->real_ndev);
359 #endif
360
361 /* return NETDEV_TX_OK; */
362 return ret;
363}
364
365static const struct net_device_ops wilc_wfi_netdev_ops = {
366 .ndo_start_xmit = WILC_WFI_mon_xmit,
367
368};
369
c5c77ba1
JK
370/**
371 * @brief WILC_WFI_mon_setup
372 * @details
373 * @param[in]
374 * @return int : Return 0 on Success
375 * @author mdaftedar
376 * @date 12 JUL 2012
377 * @version 1.0
378 */
379static void WILC_WFI_mon_setup(struct net_device *dev)
380{
381
382 dev->netdev_ops = &wilc_wfi_netdev_ops;
383 /* dev->destructor = free_netdev; */
384 PRINT_INFO(CORECONFIG_DBG, "In Ethernet setup function\n");
385 ether_setup(dev);
7d9e437d 386 dev->priv_flags |= IFF_NO_QUEUE;
c5c77ba1 387 dev->type = ARPHRD_IEEE80211_RADIOTAP;
8ca1b55a 388 eth_zero_addr(dev->dev_addr);
c5c77ba1
JK
389
390 #ifdef USE_WIRELESS
391 {
392 /* u8 * mac_add; */
393 unsigned char mac_add[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x8f};
394 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
63d03e47 395 /* mac_add = (u8*)WILC_MALLOC(ETH_ALEN); */
c5c77ba1
JK
396 /* status = host_int_get_MacAddress(priv->hWILCWFIDrv,mac_add); */
397 /* mac_add[ETH_ALEN-1]+=1; */
398 memcpy(dev->dev_addr, mac_add, ETH_ALEN);
399 }
400 #else
401 dev->dev_addr[0] = 0x12;
402 #endif
403
404}
405
406/**
407 * @brief WILC_WFI_init_mon_interface
408 * @details
409 * @param[in]
410 * @return int : Return 0 on Success
411 * @author mdaftedar
412 * @date 12 JUL 2012
413 * @version 1.0
414 */
057d1e97 415struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_device *real_dev)
c5c77ba1
JK
416{
417
418
4e4467fd 419 u32 ret = WILC_SUCCESS;
c5c77ba1
JK
420 struct WILC_WFI_mon_priv *priv;
421
422 /*If monitor interface is already initialized, return it*/
423 if (wilc_wfi_mon) {
424 return wilc_wfi_mon;
425 }
c5c77ba1
JK
426
427 wilc_wfi_mon = alloc_etherdev(sizeof(struct WILC_WFI_mon_priv));
428 if (!wilc_wfi_mon) {
429 PRINT_ER("failed to allocate memory\n");
430 return NULL;
431
432 }
433
434 wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
435 strncpy(wilc_wfi_mon->name, name, IFNAMSIZ);
436 wilc_wfi_mon->name[IFNAMSIZ - 1] = 0;
437 wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops;
438
439 ret = register_netdevice(wilc_wfi_mon);
440 if (ret) {
441 PRINT_ER(" register_netdevice failed (%d)\n", ret);
442 return NULL;
443 }
444 priv = netdev_priv(wilc_wfi_mon);
445 if (priv == NULL) {
446 PRINT_ER("private structure is NULL\n");
447 return NULL;
448 }
449
450 priv->real_ndev = real_dev;
451
452 return wilc_wfi_mon;
453}
454
455/**
456 * @brief WILC_WFI_deinit_mon_interface
457 * @details
458 * @param[in]
459 * @return int : Return 0 on Success
460 * @author mdaftedar
461 * @date 12 JUL 2012
462 * @version 1.0
463 */
a96c47e1 464int WILC_WFI_deinit_mon_interface(void)
c5c77ba1
JK
465{
466 bool rollback_lock = false;
467
468 if (wilc_wfi_mon != NULL) {
469 PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n");
470 PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n");
471 if (rtnl_is_locked()) {
472 rtnl_unlock();
473 rollback_lock = true;
474 }
475 PRINT_D(HOSTAPD_DBG, "Unregister netdev\n");
476 unregister_netdev(wilc_wfi_mon);
477 /* free_netdev(wilc_wfi_mon); */
478
479 if (rollback_lock) {
480 rtnl_lock();
481 rollback_lock = false;
482 }
483 wilc_wfi_mon = NULL;
484 }
485 return WILC_SUCCESS;
486
487}
488#endif /* WILC_AP_EXTERNAL_MLME */
This page took 0.088197 seconds and 5 git commands to generate.