3 * @brief File Operations OS wrapper functionality
5 * @sa wilc_wfi_netdevice.h
11 #include "wilc_wfi_cfgoperations.h"
12 #include "linux_wlan_common.h"
13 #include "wilc_wlan_if.h"
14 #include "wilc_wlan.h"
16 #ifdef WILC_FULLY_HOSTING_AP
17 #include "wilc_host_ap.h"
19 #ifdef WILC_AP_EXTERNAL_MLME
21 #include "wilc_wfi_cfgoperations.h"
24 struct wilc_wfi_radiotap_hdr
{
25 struct ieee80211_radiotap_header hdr
;
28 } __attribute__((packed
));
30 struct wilc_wfi_radiotap_cb_hdr
{
31 struct ieee80211_radiotap_header hdr
;
36 } __attribute__((packed
));
38 extern linux_wlan_t
*g_linux_wlan
;
40 static struct net_device
*wilc_wfi_mon
; /* global monitor netdev */
43 extern int WILC_WFI_Tx(struct sk_buff
*skb
, struct net_device
*dev
);
45 extern int mac_xmit(struct sk_buff
*skb
, struct net_device
*dev
);
51 u8 broadcast
[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
53 * @brief WILC_WFI_monitor_rx
56 * @return int : Return 0 on Success
62 #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
63 #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
64 #define IS_MANAGMEMENT 0x100
65 #define IS_MANAGMEMENT_CALLBACK 0x080
66 #define IS_MGMT_STATUS_SUCCES 0x040
67 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
69 void WILC_WFI_monitor_rx(uint8_t *buff
, uint32_t size
)
71 uint32_t header
, pkt_offset
;
72 struct sk_buff
*skb
= NULL
;
73 struct wilc_wfi_radiotap_hdr
*hdr
;
74 struct wilc_wfi_radiotap_cb_hdr
*cb_hdr
;
76 PRINT_INFO(HOSTAPD_DBG
, "In monitor interface receive function\n");
78 /* struct WILC_WFI_priv *priv = netdev_priv(dev); */
80 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
83 if (wilc_wfi_mon
== NULL
)
86 if (!netif_running(wilc_wfi_mon
)) {
87 PRINT_INFO(HOSTAPD_DBG
, "Monitor interface already RUNNING\n");
92 memcpy(&header
, (buff
- HOST_HDR_OFFSET
), HOST_HDR_OFFSET
);
94 /* The packet offset field conain info about what type of managment frame */
95 /* we are dealing with and ack status */
96 pkt_offset
= GET_PKT_OFFSET(header
);
98 if (pkt_offset
& IS_MANAGMEMENT_CALLBACK
) {
100 /* hostapd callback mgmt frame */
102 skb
= dev_alloc_skb(size
+ sizeof(struct wilc_wfi_radiotap_cb_hdr
));
104 PRINT_INFO(HOSTAPD_DBG
, "Monitor if : No memory to allocate skb");
108 memcpy(skb_put(skb
, size
), buff
, size
);
110 cb_hdr
= (struct wilc_wfi_radiotap_cb_hdr
*) skb_push(skb
, sizeof(*cb_hdr
));
111 memset(cb_hdr
, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr
));
113 cb_hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
115 cb_hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr
));
117 cb_hdr
->hdr
.it_present
= cpu_to_le32(
118 (1 << IEEE80211_RADIOTAP_RATE
) |
119 (1 << IEEE80211_RADIOTAP_TX_FLAGS
));
121 cb_hdr
->rate
= 5; /* txrate->bitrate / 5; */
123 if (pkt_offset
& IS_MGMT_STATUS_SUCCES
) {
125 cb_hdr
->tx_flags
= IEEE80211_RADIOTAP_F_TX_RTS
;
127 cb_hdr
->tx_flags
= IEEE80211_RADIOTAP_F_TX_FAIL
;
132 skb
= dev_alloc_skb(size
+ sizeof(struct wilc_wfi_radiotap_hdr
));
135 PRINT_INFO(HOSTAPD_DBG
, "Monitor if : No memory to allocate skb");
139 /* skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); */
140 /* if (skb == NULL) */
143 memcpy(skb_put(skb
, size
), buff
, size
);
144 hdr
= (struct wilc_wfi_radiotap_hdr
*) skb_push(skb
, sizeof(*hdr
));
145 memset(hdr
, 0, sizeof(struct wilc_wfi_radiotap_hdr
));
146 hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
147 /* hdr->hdr.it_pad = 0; */
148 hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr
));
149 PRINT_INFO(HOSTAPD_DBG
, "Radiotap len %d\n", hdr
->hdr
.it_len
);
150 hdr
->hdr
.it_present
= cpu_to_le32
151 (1 << IEEE80211_RADIOTAP_RATE
); /* | */
152 /* (1 << IEEE80211_RADIOTAP_CHANNEL)); */
153 PRINT_INFO(HOSTAPD_DBG
, "Presentflags %d\n", hdr
->hdr
.it_present
);
154 hdr
->rate
= 5; /* txrate->bitrate / 5; */
158 /* if(INFO || if(skb->data[9] == 0x00 || skb->data[9] == 0xb0))
160 * for(i=0;i<skb->len;i++)
161 * PRINT_INFO(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,skb->data[i]);
165 skb
->dev
= wilc_wfi_mon
;
166 skb_set_mac_header(skb
, 0);
167 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
168 skb
->pkt_type
= PACKET_OTHERHOST
;
169 skb
->protocol
= htons(ETH_P_802_2
);
170 memset(skb
->cb
, 0, sizeof(skb
->cb
));
177 struct tx_complete_mon_data
{
182 static void mgmt_tx_complete(void *priv
, int status
)
185 /* struct sk_buff *skb2; */
186 /* struct wilc_wfi_radiotap_cb_hdr *cb_hdr; */
188 struct tx_complete_mon_data
*pv_data
= (struct tx_complete_mon_data
*)priv
;
189 u8
*buf
= pv_data
->buff
;
194 if (INFO
|| buf
[0] == 0x10 || buf
[0] == 0xb0)
195 PRINT_INFO(HOSTAPD_DBG
, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data
->size
, pv_data
->buff
);
197 PRINT_INFO(HOSTAPD_DBG
, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data
->size
, pv_data
->buff
);
201 /* //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 )
203 * skb2 = dev_alloc_skb(pv_data->size+sizeof(struct wilc_wfi_radiotap_cb_hdr));
205 * memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size);
207 * cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
208 * memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
210 * cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
212 * cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
214 * cb_hdr->hdr.it_present = cpu_to_le32(
215 * (1 << IEEE80211_RADIOTAP_RATE) |
216 * (1 << IEEE80211_RADIOTAP_TX_FLAGS));
218 * cb_hdr->rate = 5;//txrate->bitrate / 5;
219 * cb_hdr->tx_flags = 0x0004;
221 * skb2->dev = wilc_wfi_mon;
222 * skb_set_mac_header(skb2, 0);
223 * skb2->ip_summed = CHECKSUM_UNNECESSARY;
224 * skb2->pkt_type = PACKET_OTHERHOST;
225 * skb2->protocol = htons(ETH_P_802_2);
226 * memset(skb2->cb, 0, sizeof(skb2->cb));
231 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
232 #ifndef WILC_FULLY_HOSTING_AP
233 kfree(pv_data
->buff
);
238 static int mon_mgmt_tx(struct net_device
*dev
, const u8
*buf
, size_t len
)
241 struct tx_complete_mon_data
*mgmt_tx
= NULL
;
244 PRINT_D(HOSTAPD_DBG
, "ERROR: dev == NULL\n");
247 nic
= netdev_priv(dev
);
249 netif_stop_queue(dev
);
250 mgmt_tx
= (struct tx_complete_mon_data
*)kmalloc(sizeof(struct tx_complete_mon_data
), GFP_ATOMIC
);
251 if (mgmt_tx
== NULL
) {
252 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
256 #ifdef WILC_FULLY_HOSTING_AP
257 /* add space for the pointer to tx_complete_mon_data */
258 len
+= sizeof(struct tx_complete_mon_data
*);
261 mgmt_tx
->buff
= kmalloc(len
, GFP_ATOMIC
);
262 if (mgmt_tx
->buff
== NULL
) {
263 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
270 #ifndef WILC_FULLY_HOSTING_AP
271 memcpy(mgmt_tx
->buff
, buf
, len
);
273 memcpy(mgmt_tx
->buff
, buf
, len
- sizeof(struct tx_complete_mon_data
*));
274 memcpy((mgmt_tx
->buff
) + (len
- sizeof(struct tx_complete_mon_data
*)), &mgmt_tx
, sizeof(struct tx_complete_mon_data
*));
276 /* filter data frames to handle it's PS */
277 if (filter_monitor_data_frames((mgmt_tx
->buff
), len
) == true) {
281 #endif /* WILC_FULLY_HOSTING_AP */
283 g_linux_wlan
->oup
.wlan_add_mgmt_to_tx_que(mgmt_tx
, mgmt_tx
->buff
, mgmt_tx
->size
, mgmt_tx_complete
);
285 netif_wake_queue(dev
);
290 * @brief WILC_WFI_mon_xmit
293 * @return int : Return 0 on Success
298 static netdev_tx_t
WILC_WFI_mon_xmit(struct sk_buff
*skb
,
299 struct net_device
*dev
)
301 struct ieee80211_radiotap_header
*rtap_hdr
;
302 u32 rtap_len
, i
, ret
= 0;
303 struct WILC_WFI_mon_priv
*mon_priv
;
305 struct sk_buff
*skb2
;
306 struct wilc_wfi_radiotap_cb_hdr
*cb_hdr
;
309 if (wilc_wfi_mon
== NULL
)
312 /* if(skb->data[3] == 0x10 || skb->data[3] == 0xb0) */
314 mon_priv
= netdev_priv(wilc_wfi_mon
);
316 if (mon_priv
== NULL
) {
317 PRINT_ER("Monitor interface private structure is NULL\n");
321 rtap_hdr
= (struct ieee80211_radiotap_header
*)skb
->data
;
323 rtap_len
= ieee80211_get_radiotap_len(skb
->data
);
324 if (skb
->len
< rtap_len
) {
325 PRINT_ER("Error in radiotap header\n");
328 /* skip the radiotap header */
329 PRINT_INFO(HOSTAPD_DBG
, "Radiotap len: %d\n", rtap_len
);
332 for (i
= 0; i
< rtap_len
; i
++)
333 PRINT_INFO(HOSTAPD_DBG
, "Radiotap_hdr[%d] %02x\n", i
, skb
->data
[i
]);
335 /* Skip the ratio tap header */
336 skb_pull(skb
, rtap_len
);
338 if (skb
->data
[0] == 0xc0)
339 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]);
341 if (skb
->data
[0] == 0xc0 && (!(memcmp(broadcast
, &skb
->data
[4], 6)))) {
342 skb2
= dev_alloc_skb(skb
->len
+ sizeof(struct wilc_wfi_radiotap_cb_hdr
));
344 memcpy(skb_put(skb2
, skb
->len
), skb
->data
, skb
->len
);
346 cb_hdr
= (struct wilc_wfi_radiotap_cb_hdr
*) skb_push(skb2
, sizeof(*cb_hdr
));
347 memset(cb_hdr
, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr
));
349 cb_hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
351 cb_hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr
));
353 cb_hdr
->hdr
.it_present
= cpu_to_le32(
354 (1 << IEEE80211_RADIOTAP_RATE
) |
355 (1 << IEEE80211_RADIOTAP_TX_FLAGS
));
357 cb_hdr
->rate
= 5; /* txrate->bitrate / 5; */
358 cb_hdr
->tx_flags
= 0x0004;
360 skb2
->dev
= wilc_wfi_mon
;
361 skb_set_mac_header(skb2
, 0);
362 skb2
->ip_summed
= CHECKSUM_UNNECESSARY
;
363 skb2
->pkt_type
= PACKET_OTHERHOST
;
364 skb2
->protocol
= htons(ETH_P_802_2
);
365 memset(skb2
->cb
, 0, sizeof(skb2
->cb
));
371 skb
->dev
= mon_priv
->real_ndev
;
373 PRINT_INFO(HOSTAPD_DBG
, "Skipping the radiotap header\n");
377 /* actual deliver of data is device-specific, and not shown here */
378 PRINT_INFO(HOSTAPD_DBG
, "SKB netdevice name = %s\n", skb
->dev
->name
);
379 PRINT_INFO(HOSTAPD_DBG
, "MONITOR real dev name = %s\n", mon_priv
->real_ndev
->name
);
382 ret
= WILC_WFI_Tx(skb
, mon_priv
->real_ndev
);
384 /* Identify if Ethernet or MAC header (data or mgmt) */
385 memcpy(srcAdd
, &skb
->data
[10], 6);
386 memcpy(bssid
, &skb
->data
[16], 6);
387 /* if source address and bssid fields are equal>>Mac header */
388 /*send it to mgmt frames handler */
389 if (!(memcmp(srcAdd
, bssid
, 6))) {
390 mon_mgmt_tx(mon_priv
->real_ndev
, skb
->data
, skb
->len
);
393 ret
= mac_xmit(skb
, mon_priv
->real_ndev
);
396 /* return NETDEV_TX_OK; */
400 static const struct net_device_ops wilc_wfi_netdev_ops
= {
401 .ndo_start_xmit
= WILC_WFI_mon_xmit
,
405 #ifdef WILC_FULLY_HOSTING_AP
407 * @brief WILC_mgm_HOSTAPD_ACK
408 * @details report the status of transmitted mgmt frames to HOSTAPD
409 * @param[in] priv : pointer to tx_complete_mon_data struct
410 * bStatus : status of transmission
411 * @author Abd Al-Rahman Diab
415 void WILC_mgm_HOSTAPD_ACK(void *priv
, bool bStatus
)
418 struct wilc_wfi_radiotap_cb_hdr
*cb_hdr
;
420 struct tx_complete_mon_data
*pv_data
= (struct tx_complete_mon_data
*)priv
;
421 u8
*buf
= pv_data
->buff
;
423 /* len of the original frame without the added pointer at the tail */
424 u16 u16len
= (pv_data
->size
) - sizeof(struct tx_complete_mon_data
*);
428 * if(INFO || buf[0] == 0x10 || buf[0] == 0xb0)
429 * PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",u16len,pv_data->buff);
431 * PRINT_D(HOSTAPD_DBG,"Couldn't send packet - Size = %d - Address = %p.\n",u16len,pv_data->buff);
435 /* (skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 ) */
437 skb
= dev_alloc_skb(u16len
+ sizeof(struct wilc_wfi_radiotap_cb_hdr
));
439 memcpy(skb_put(skb
, u16len
), pv_data
->buff
, u16len
);
441 cb_hdr
= (struct wilc_wfi_radiotap_cb_hdr
*) skb_push(skb
, sizeof(*cb_hdr
));
442 memset(cb_hdr
, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr
));
444 cb_hdr
->hdr
.it_version
= 0; /* PKTHDR_RADIOTAP_VERSION; */
446 cb_hdr
->hdr
.it_len
= cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr
));
448 cb_hdr
->hdr
.it_present
= cpu_to_le32(
449 (1 << IEEE80211_RADIOTAP_RATE
) |
450 (1 << IEEE80211_RADIOTAP_TX_FLAGS
));
452 cb_hdr
->rate
= 5; /* txrate->bitrate / 5; */
457 cb_hdr
->tx_flags
= IEEE80211_RADIOTAP_F_TX_RTS
;
459 cb_hdr
->tx_flags
= IEEE80211_RADIOTAP_F_TX_FAIL
;
462 skb
->dev
= wilc_wfi_mon
;
463 skb_set_mac_header(skb
, 0);
464 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
465 skb
->pkt_type
= PACKET_OTHERHOST
;
466 skb
->protocol
= htons(ETH_P_802_2
);
467 memset(skb
->cb
, 0, sizeof(skb
->cb
));
472 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
473 kfree(pv_data
->buff
);
478 #endif /* WILC_FULLY_HOSTING_AP */
481 * @brief WILC_WFI_mon_setup
484 * @return int : Return 0 on Success
489 static void WILC_WFI_mon_setup(struct net_device
*dev
)
492 dev
->netdev_ops
= &wilc_wfi_netdev_ops
;
493 /* dev->destructor = free_netdev; */
494 PRINT_INFO(CORECONFIG_DBG
, "In Ethernet setup function\n");
496 dev
->tx_queue_len
= 0;
497 dev
->type
= ARPHRD_IEEE80211_RADIOTAP
;
498 memset(dev
->dev_addr
, 0, ETH_ALEN
);
503 unsigned char mac_add
[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x8f};
504 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
505 /* mac_add = (u8*)WILC_MALLOC(ETH_ALEN); */
506 /* status = host_int_get_MacAddress(priv->hWILCWFIDrv,mac_add); */
507 /* mac_add[ETH_ALEN-1]+=1; */
508 memcpy(dev
->dev_addr
, mac_add
, ETH_ALEN
);
511 dev
->dev_addr
[0] = 0x12;
517 * @brief WILC_WFI_init_mon_interface
520 * @return int : Return 0 on Success
525 struct net_device
*WILC_WFI_init_mon_interface(const char *name
, struct net_device
*real_dev
)
529 u32 ret
= WILC_SUCCESS
;
530 struct WILC_WFI_mon_priv
*priv
;
532 /*If monitor interface is already initialized, return it*/
537 wilc_wfi_mon
= alloc_netdev(sizeof(struct WILC_WFI_mon_priv
), name
, WILC_WFI_mon_setup
);
538 if (wilc_wfi_mon
== NULL
) {
539 PRINT_ER("Failed to allocate netdevice\n");
544 PRINT_INFO(HOSTAPD_DBG
, "Monitor interface name %s\n", wilc_wfi_mon
->name
);
547 ret
= dev_alloc_name(wilc_wfi_mon
, wilc_wfi_mon
->name
);
552 priv
= netdev_priv(wilc_wfi_mon
);
554 PRINT_ER("private structure is NULL\n");
558 priv
->real_ndev
= real_dev
;
561 ret
= register_netdevice(wilc_wfi_mon
);
565 PRINT_ER("Failed to register netdevice\n");
578 free_netdev(wilc_wfi_mon
);
582 wilc_wfi_mon
= alloc_etherdev(sizeof(struct WILC_WFI_mon_priv
));
584 PRINT_ER("failed to allocate memory\n");
589 wilc_wfi_mon
->type
= ARPHRD_IEEE80211_RADIOTAP
;
590 strncpy(wilc_wfi_mon
->name
, name
, IFNAMSIZ
);
591 wilc_wfi_mon
->name
[IFNAMSIZ
- 1] = 0;
592 wilc_wfi_mon
->netdev_ops
= &wilc_wfi_netdev_ops
;
594 ret
= register_netdevice(wilc_wfi_mon
);
596 PRINT_ER(" register_netdevice failed (%d)\n", ret
);
599 priv
= netdev_priv(wilc_wfi_mon
);
601 PRINT_ER("private structure is NULL\n");
605 priv
->real_ndev
= real_dev
;
611 * @brief WILC_WFI_deinit_mon_interface
614 * @return int : Return 0 on Success
619 int WILC_WFI_deinit_mon_interface()
621 bool rollback_lock
= false;
623 if (wilc_wfi_mon
!= NULL
) {
624 PRINT_D(HOSTAPD_DBG
, "In Deinit monitor interface\n");
625 PRINT_D(HOSTAPD_DBG
, "RTNL is being locked\n");
626 if (rtnl_is_locked()) {
628 rollback_lock
= true;
630 PRINT_D(HOSTAPD_DBG
, "Unregister netdev\n");
631 unregister_netdev(wilc_wfi_mon
);
632 /* free_netdev(wilc_wfi_mon); */
636 rollback_lock
= false;
643 #endif /* WILC_AP_EXTERNAL_MLME */