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