2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #include <linux/sched.h>
29 #include "rt_config.h"
31 ULONG RTDebugLevel = RT_DEBUG_ERROR;
34 // for wireless system event message
35 char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
36 // system status event
37 "had associated successfully", /* IW_ASSOC_EVENT_FLAG */
38 "had disassociated", /* IW_DISASSOC_EVENT_FLAG */
39 "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */
40 "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */
41 "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */
42 "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
43 "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */
44 "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */
45 "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */
46 "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */
47 "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
48 "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
49 "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
50 "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
51 "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
52 "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */
53 "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
54 "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */
55 "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
58 // for wireless IDS_spoof_attack event message
59 char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
60 "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */
61 "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
62 "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
63 "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
64 "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */
65 "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */
66 "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */
67 "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */
68 "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
69 "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */
72 // for wireless IDS_flooding_attack event message
73 char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
74 "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */
75 "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
76 "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
77 "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
78 "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */
79 "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */
80 "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
84 VOID RTMP_SetPeriodicTimer(
85 IN NDIS_MINIPORT_TIMER *pTimer,
86 IN unsigned long timeout)
88 timeout = ((timeout*OS_HZ) / 1000);
89 pTimer->expires = jiffies + timeout;
93 /* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
94 VOID RTMP_OS_Init_Timer(
96 IN NDIS_MINIPORT_TIMER *pTimer,
97 IN TIMER_FUNCTION function,
101 pTimer->data = (unsigned long)data;
102 pTimer->function = function;
106 VOID RTMP_OS_Add_Timer(
107 IN NDIS_MINIPORT_TIMER *pTimer,
108 IN unsigned long timeout)
110 if (timer_pending(pTimer))
113 timeout = ((timeout*OS_HZ) / 1000);
114 pTimer->expires = jiffies + timeout;
118 VOID RTMP_OS_Mod_Timer(
119 IN NDIS_MINIPORT_TIMER *pTimer,
120 IN unsigned long timeout)
122 timeout = ((timeout*OS_HZ) / 1000);
123 mod_timer(pTimer, jiffies + timeout);
126 VOID RTMP_OS_Del_Timer(
127 IN NDIS_MINIPORT_TIMER *pTimer,
128 OUT BOOLEAN *pCancelled)
130 if (timer_pending(pTimer))
132 *pCancelled = del_timer_sync(pTimer);
141 VOID RTMP_OS_Release_Packet(
142 IN PRTMP_ADAPTER pAd,
143 IN PQUEUE_ENTRY pEntry)
145 //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
148 // Unify all delay routine by using udelay
154 for (i = 0; i < (usec / 50); i++)
161 void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
163 time->u.LowPart = jiffies;
166 // pAd MUST allow to be NULL
167 NDIS_STATUS os_alloc_mem(
168 IN RTMP_ADAPTER *pAd,
172 *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
174 return (NDIS_STATUS_SUCCESS);
176 return (NDIS_STATUS_FAILURE);
179 // pAd MUST allow to be NULL
180 NDIS_STATUS os_free_mem(
181 IN PRTMP_ADAPTER pAd,
187 return (NDIS_STATUS_SUCCESS);
193 PNDIS_PACKET RtmpOSNetPktAlloc(
194 IN RTMP_ADAPTER *pAd,
198 /* Add 2 more bytes for ip header alignment*/
199 skb = dev_alloc_skb(size+2);
201 return ((PNDIS_PACKET)skb);
205 PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
206 IN PRTMP_ADAPTER pAd,
211 pkt = dev_alloc_skb(Length);
215 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
220 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
223 return (PNDIS_PACKET) pkt;
227 PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
228 IN PRTMP_ADAPTER pAd,
231 OUT PVOID *VirtualAddress)
235 pkt = dev_alloc_skb(Length);
239 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
244 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
245 *VirtualAddress = (PVOID) pkt->data;
249 *VirtualAddress = (PVOID) NULL;
252 return (PNDIS_PACKET) pkt;
256 VOID build_tx_packet(
257 IN PRTMP_ADAPTER pAd,
258 IN PNDIS_PACKET pPacket,
263 struct sk_buff *pTxPkt;
266 pTxPkt = RTPKT_TO_OSPKT(pPacket);
268 NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
271 VOID RTMPFreeAdapter(
272 IN PRTMP_ADAPTER pAd)
274 POS_COOKIE os_cookie;
277 os_cookie=(POS_COOKIE)pAd->OS_Cookie;
280 kfree(pAd->BeaconBuf);
283 NdisFreeSpinLock(&pAd->MgmtRingLock);
286 NdisFreeSpinLock(&pAd->RxRingLock);
288 NdisFreeSpinLock(&pAd->McuCmdLock);
290 #endif // RTMP_MAC_PCI //
292 for (index =0 ; index < NUM_OF_TX_RING; index++)
294 NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
295 NdisFreeSpinLock(&pAd->DeQueueLock[index]);
296 pAd->DeQueueRunning[index] = FALSE;
299 NdisFreeSpinLock(&pAd->irq_lock);
302 vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
307 BOOLEAN OS_Need_Clone_Packet(void)
315 ========================================================================
318 clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
319 must have only one NDIS BUFFER
320 return - byte copied. 0 means can't create NDIS PACKET
321 NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
324 pAd Pointer to our adapter
325 pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
326 *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet.
334 ========================================================================
336 NDIS_STATUS RTMPCloneNdisPacket(
337 IN PRTMP_ADAPTER pAd,
338 IN BOOLEAN pInsAMSDUHdr,
339 IN PNDIS_PACKET pInPacket,
340 OUT PNDIS_PACKET *ppOutPacket)
348 // 1. Allocate a packet
349 pkt = dev_alloc_skb(2048);
353 return NDIS_STATUS_FAILURE;
356 skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
357 NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
358 *ppOutPacket = OSPKT_TO_RTPKT(pkt);
361 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
363 printk("###Clone###\n");
365 return NDIS_STATUS_SUCCESS;
369 // the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
370 NDIS_STATUS RTMPAllocateNdisPacket(
371 IN PRTMP_ADAPTER pAd,
372 OUT PNDIS_PACKET *ppPacket,
378 PNDIS_PACKET pPacket;
382 // 1. Allocate a packet
383 pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING);
388 printk("RTMPAllocateNdisPacket Fail\n\n");
390 return NDIS_STATUS_FAILURE;
393 // 2. clone the frame content
395 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
397 NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
399 // 3. update length of packet
400 skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
402 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
403 // printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket));
405 return NDIS_STATUS_SUCCESS;
409 ========================================================================
411 This routine frees a miniport internally allocated NDIS_PACKET and its
412 corresponding NDIS_BUFFER and allocated memory.
413 ========================================================================
415 VOID RTMPFreeNdisPacket(
416 IN PRTMP_ADAPTER pAd,
417 IN PNDIS_PACKET pPacket)
419 dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
423 // IRQL = DISPATCH_LEVEL
424 // NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
425 // scatter gather buffer
426 NDIS_STATUS Sniff2BytesFromNdisBuffer(
427 IN PNDIS_BUFFER pFirstBuffer,
428 IN UCHAR DesiredOffset,
432 *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
433 *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
435 return NDIS_STATUS_SUCCESS;
439 void RTMP_QueryPacketInfo(
440 IN PNDIS_PACKET pPacket,
441 OUT PACKET_INFO *pPacketInfo,
442 OUT PUCHAR *pSrcBufVA,
443 OUT UINT *pSrcBufLen)
445 pPacketInfo->BufferCount = 1;
446 pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
447 pPacketInfo->PhysicalBufferCount = 1;
448 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
450 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
451 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
454 void RTMP_QueryNextPacketInfo(
455 IN PNDIS_PACKET *ppPacket,
456 OUT PACKET_INFO *pPacketInfo,
457 OUT PUCHAR *pSrcBufVA,
458 OUT UINT *pSrcBufLen)
460 PNDIS_PACKET pPacket = NULL;
463 pPacket = GET_OS_PKT_NEXT(*ppPacket);
467 pPacketInfo->BufferCount = 1;
468 pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
469 pPacketInfo->PhysicalBufferCount = 1;
470 pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
472 *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
473 *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
474 *ppPacket = GET_OS_PKT_NEXT(pPacket);
478 pPacketInfo->BufferCount = 0;
479 pPacketInfo->pFirstBuffer = NULL;
480 pPacketInfo->PhysicalBufferCount = 0;
481 pPacketInfo->TotalPacketLength = 0;
490 PNDIS_PACKET DuplicatePacket(
491 IN PRTMP_ADAPTER pAd,
492 IN PNDIS_PACKET pPacket,
493 IN UCHAR FromWhichBSSID)
496 PNDIS_PACKET pRetPacket = NULL;
500 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
501 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
504 skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
507 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
508 pRetPacket = OSPKT_TO_RTPKT(skb);
515 PNDIS_PACKET duplicate_pkt(
516 IN PRTMP_ADAPTER pAd,
517 IN PUCHAR pHeader802_3,
521 IN UCHAR FromWhichBSSID)
524 PNDIS_PACKET pPacket = NULL;
527 if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
530 NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
531 skb_put(skb, HdrLen);
532 NdisMoveMemory(skb->tail, pData, DataSize);
533 skb_put(skb, DataSize);
534 skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
535 pPacket = OSPKT_TO_RTPKT(skb);
542 #define TKIP_TX_MIC_SIZE 8
543 PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
544 IN PRTMP_ADAPTER pAd,
545 IN PNDIS_PACKET pPacket)
547 struct sk_buff *skb, *newskb;
550 skb = RTPKT_TO_OSPKT(pPacket);
551 if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
553 // alloc a new skb and copy the packet
554 newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
555 dev_kfree_skb_any(skb);
558 DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
564 return OSPKT_TO_RTPKT(skb);
570 PNDIS_PACKET ClonePacket(
571 IN PRTMP_ADAPTER pAd,
572 IN PNDIS_PACKET pPacket,
576 struct sk_buff *pRxPkt;
577 struct sk_buff *pClonedPkt;
580 pRxPkt = RTPKT_TO_OSPKT(pPacket);
583 pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
587 // set the correct dataptr and data len
588 pClonedPkt->dev = pRxPkt->dev;
589 pClonedPkt->data = pData;
590 pClonedPkt->len = DataSize;
591 pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
592 ASSERT(DataSize < 1530);
598 // change OS packet DataPtr and DataLen
600 void update_os_packet_info(
601 IN PRTMP_ADAPTER pAd,
603 IN UCHAR FromWhichBSSID)
605 struct sk_buff *pOSPkt;
607 ASSERT(pRxBlk->pRxPacket);
608 pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
610 pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
611 pOSPkt->data = pRxBlk->pData;
612 pOSPkt->len = pRxBlk->DataSize;
613 pOSPkt->tail = pOSPkt->data + pOSPkt->len;
617 void wlan_802_11_to_802_3_packet(
618 IN PRTMP_ADAPTER pAd,
620 IN PUCHAR pHeader802_3,
621 IN UCHAR FromWhichBSSID)
623 struct sk_buff *pOSPkt;
625 ASSERT(pRxBlk->pRxPacket);
626 ASSERT(pHeader802_3);
628 pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
630 pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
631 pOSPkt->data = pRxBlk->pData;
632 pOSPkt->len = pRxBlk->DataSize;
633 pOSPkt->tail = pOSPkt->data + pOSPkt->len;
640 NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
645 void announce_802_3_packet(
646 IN PRTMP_ADAPTER pAd,
647 IN PNDIS_PACKET pPacket)
650 struct sk_buff *pRxPkt;
654 pRxPkt = RTPKT_TO_OSPKT(pPacket);
656 /* Push up the protocol stack */
657 pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
663 PRTMP_SCATTER_GATHER_LIST
664 rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
666 sg->NumberOfElements = 1;
667 sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
668 sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
672 void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
677 if (RTDebugLevel < RT_DEBUG_TRACE)
681 printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen);
682 for (x=0; x<SrcBufLen; x++)
685 printk("0x%04x : ", x);
686 printk("%02x ", ((unsigned char)pt[x]));
687 if (x%16 == 15) printk("\n");
693 ========================================================================
696 Send log message through wireless event
698 Support standard iw_event with IWEVCUSTOM. It is used below.
700 iwreq_data.data.flags is used to store event_flag that is defined by user.
701 iwreq_data.data.length is the length of the event log.
703 The format of the event log is composed of the entry's MAC address and
704 the desired log message (refer to pWirelessEventText).
706 ex: 11:22:33:44:55:66 has associated successfully
708 p.s. The requirement of Wireless Extension is v15 or newer.
710 ========================================================================
712 VOID RTMPSendWirelessEvent(
713 IN PRTMP_ADAPTER pAd,
714 IN USHORT Event_flag,
720 //union iwreq_data wrqu;
721 PSTRING pBuf = NULL, pBufPtr = NULL;
722 USHORT event, type, BufLen;
723 UCHAR event_table_len = 0;
725 type = Event_flag & 0xFF00;
726 event = Event_flag & 0x00FF;
730 case IW_SYS_EVENT_FLAG_START:
731 event_table_len = IW_SYS_EVENT_TYPE_NUM;
734 case IW_SPOOF_EVENT_FLAG_START:
735 event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
738 case IW_FLOOD_EVENT_FLAG_START:
739 event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
743 if (event_table_len == 0)
745 DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __func__, type));
749 if (event >= event_table_len)
751 DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __func__, event));
755 //Allocate memory and copy the msg.
756 if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
758 //Prepare the payload
759 memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
764 pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
765 else if (BssIdx < MAX_MBSSID_NUM)
766 pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
768 pBufPtr += sprintf(pBufPtr, "(RT2860) ");
770 if (type == IW_SYS_EVENT_FLAG_START)
771 pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
772 else if (type == IW_SPOOF_EVENT_FLAG_START)
773 pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
774 else if (type == IW_FLOOD_EVENT_FLAG_START)
775 pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
777 pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
779 pBufPtr[pBufPtr - pBuf] = '\0';
780 BufLen = pBufPtr - pBuf;
782 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen);
783 //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf));
788 DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __func__));
791 void send_monitor_packets(
792 IN PRTMP_ADAPTER pAd,
795 struct sk_buff *pOSPkt;
796 wlan_ng_prism2_header *ph;
798 USHORT header_len = 0;
799 UCHAR temp_header[40] = {0};
801 u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38
802 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10,
803 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80};
806 ASSERT(pRxBlk->pRxPacket);
807 if (pRxBlk->DataSize < 10)
809 DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __func__, pRxBlk->DataSize));
810 goto err_free_sk_buff;
813 if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
815 DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%zu)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
816 goto err_free_sk_buff;
819 pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
820 pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
821 if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
823 pRxBlk->DataSize -= LENGTH_802_11;
824 if ((pRxBlk->pHeader->FC.ToDs == 1) &&
825 (pRxBlk->pHeader->FC.FrDs == 1))
826 header_len = LENGTH_802_11_WITH_ADDR4;
828 header_len = LENGTH_802_11;
831 if (pRxBlk->pHeader->FC.SubType & 0x08)
834 // Data skip QOS contorl field
835 pRxBlk->DataSize -=2;
838 // Order bit: A-Ralink or HTC+
839 if (pRxBlk->pHeader->FC.Order)
842 // Data skip HTC contorl field
843 pRxBlk->DataSize -= 4;
847 if (header_len <= 40)
848 NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
851 if (pRxBlk->RxD.L2PAD)
852 pRxBlk->pData += (header_len + 2);
854 pRxBlk->pData += header_len;
858 if (pRxBlk->DataSize < pOSPkt->len) {
859 skb_trim(pOSPkt,pRxBlk->DataSize);
861 skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
864 if ((pRxBlk->pData - pOSPkt->data) > 0) {
865 skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
866 skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
869 if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
870 if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
871 DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __func__));
872 goto err_free_sk_buff;
877 NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
879 ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
880 NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
882 ph->msgcode = DIDmsg_lnxind_wlansniffrm;
883 ph->msglen = sizeof(wlan_ng_prism2_header);
884 strcpy((PSTRING) ph->devname, (PSTRING) pAd->net_dev->name);
886 ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
887 ph->hosttime.status = 0;
888 ph->hosttime.len = 4;
889 ph->hosttime.data = jiffies;
891 ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
892 ph->mactime.status = 0;
894 ph->mactime.data = 0;
896 ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
901 ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
902 ph->channel.status = 0;
905 ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
907 ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
910 ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));;
912 ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
913 ph->signal.status = 0;
915 ph->signal.data = 0; //rssi + noise;
917 ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
918 ph->noise.status = 0;
922 if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
924 rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
927 if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
928 rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
930 rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
933 if (rate_index > 255)
936 ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
939 ph->rate.data = ralinkrate[rate_index];
941 ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
942 ph->frmlen.status = 0;
944 ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
947 pOSPkt->pkt_type = PACKET_OTHERHOST;
948 pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
949 pOSPkt->ip_summed = CHECKSUM_NONE;
955 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
961 /*******************************************************************************
963 Device IRQ related functions.
965 *******************************************************************************/
966 int RtmpOSIRQRequest(IN PNET_DEV pNetDev)
968 struct net_device *net_dev = pNetDev;
969 PRTMP_ADAPTER pAd = NULL;
972 GET_PAD_FROM_NET_DEV(pAd, pNetDev);
976 #ifdef RTMP_PCI_SUPPORT
977 if (pAd->infType == RTMP_DEV_INF_PCI)
979 POS_COOKIE _pObj = (POS_COOKIE)(pAd->OS_Cookie);
980 RTMP_MSI_ENABLE(pAd);
981 retval = request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ, (net_dev)->name, (net_dev));
983 printk("RT2860: request_irq ERROR(%d)\n", retval);
985 #endif // RTMP_PCI_SUPPORT //
993 int RtmpOSIRQRelease(IN PNET_DEV pNetDev)
995 struct net_device *net_dev = pNetDev;
996 PRTMP_ADAPTER pAd = NULL;
998 GET_PAD_FROM_NET_DEV(pAd, net_dev);
1002 #ifdef RTMP_PCI_SUPPORT
1003 if (pAd->infType == RTMP_DEV_INF_PCI)
1005 POS_COOKIE pObj = (POS_COOKIE)(pAd->OS_Cookie);
1006 synchronize_irq(pObj->pci_dev->irq);
1007 free_irq(pObj->pci_dev->irq, (net_dev));
1008 RTMP_MSI_DISABLE(pAd);
1010 #endif // RTMP_PCI_SUPPORT //
1017 /*******************************************************************************
1019 File open/close related functions.
1021 *******************************************************************************/
1022 RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode)
1024 struct file *filePtr;
1026 filePtr = filp_open(pPath, flag, 0);
1027 if (IS_ERR(filePtr))
1029 DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error %ld opening %s\n", __func__, -PTR_ERR(filePtr), pPath));
1032 return (RTMP_OS_FD)filePtr;
1035 int RtmpOSFileClose(RTMP_OS_FD osfd)
1037 filp_close(osfd, NULL);
1042 void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset)
1044 osfd->f_pos = offset;
1048 int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen)
1050 // The object must have a read method
1051 if (osfd->f_op && osfd->f_op->read)
1053 return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
1057 DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
1063 int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen)
1065 return osfd->f_op->write(osfd, pDataPtr, (size_t)writeLen, &osfd->f_pos);
1068 /*******************************************************************************
1070 Task create/management/kill related functions.
1072 *******************************************************************************/
1073 NDIS_STATUS RtmpOSTaskKill(
1074 IN RTMP_OS_TASK *pTask)
1077 int ret = NDIS_STATUS_FAILURE;
1079 pAd = (RTMP_ADAPTER *)pTask->priv;
1081 #ifdef KTHREAD_SUPPORT
1082 if (pTask->kthread_task)
1084 kthread_stop(pTask->kthread_task);
1085 ret = NDIS_STATUS_SUCCESS;
1088 CHECK_PID_LEGALITY(pTask->taskPID)
1090 printk("Terminate the task(%s) with pid(%d)!\n", pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1092 pTask->task_killed = 1;
1094 ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1097 printk(KERN_WARNING "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1098 pTask->taskName, GET_PID_NUMBER(pTask->taskPID), ret);
1102 wait_for_completion(&pTask->taskComplete);
1103 pTask->taskPID = THREAD_PID_INIT_VALUE;
1104 pTask->task_killed = 0;
1105 ret = NDIS_STATUS_SUCCESS;
1115 INT RtmpOSTaskNotifyToExit(
1116 IN RTMP_OS_TASK *pTask)
1119 #ifndef KTHREAD_SUPPORT
1120 complete_and_exit(&pTask->taskComplete, 0);
1127 void RtmpOSTaskCustomize(
1128 IN RTMP_OS_TASK *pTask)
1131 #ifndef KTHREAD_SUPPORT
1133 daemonize((PSTRING)&pTask->taskName[0]/*"%s",pAd->net_dev->name*/);
1135 allow_signal(SIGTERM);
1136 allow_signal(SIGKILL);
1137 current->flags |= PF_NOFREEZE;
1139 /* signal that we've started the thread */
1140 complete(&pTask->taskComplete);
1146 NDIS_STATUS RtmpOSTaskAttach(
1147 IN RTMP_OS_TASK *pTask,
1148 IN int (*fn)(void *),
1151 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
1152 pid_t pid_number = -1;
1154 #ifdef KTHREAD_SUPPORT
1155 pTask->task_killed = 0;
1156 pTask->kthread_task = NULL;
1157 pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1158 if (IS_ERR(pTask->kthread_task))
1159 status = NDIS_STATUS_FAILURE;
1161 pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1164 DBGPRINT (RT_DEBUG_ERROR, ("Attach task(%s) failed!\n", pTask->taskName));
1165 status = NDIS_STATUS_FAILURE;
1169 pTask->taskPID = GET_PID(pid_number);
1171 // Wait for the thread to start
1172 wait_for_completion(&pTask->taskComplete);
1173 status = NDIS_STATUS_SUCCESS;
1180 NDIS_STATUS RtmpOSTaskInit(
1181 IN RTMP_OS_TASK *pTask,
1182 IN PSTRING pTaskName,
1189 #ifndef KTHREAD_SUPPORT
1190 NdisZeroMemory((PUCHAR)(pTask), sizeof(RTMP_OS_TASK));
1193 len = strlen(pTaskName);
1194 len = len > (RTMP_OS_TASK_NAME_LEN -1) ? (RTMP_OS_TASK_NAME_LEN-1) : len;
1195 NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1196 pTask->priv = pPriv;
1198 #ifndef KTHREAD_SUPPORT
1199 RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1200 pTask->taskPID = THREAD_PID_INIT_VALUE;
1202 init_completion (&pTask->taskComplete);
1205 return NDIS_STATUS_SUCCESS;
1209 void RTMP_IndicateMediaState(
1210 IN PRTMP_ADAPTER pAd)
1212 if (pAd->CommonCfg.bWirelessEvent)
1214 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1216 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1220 RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1225 int RtmpOSWrielessEventSend(
1226 IN RTMP_ADAPTER *pAd,
1227 IN UINT32 eventType,
1233 union iwreq_data wrqu;
1235 memset(&wrqu, 0, sizeof(wrqu));
1238 wrqu.data.flags = flags;
1241 memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1243 if ((pData!= NULL) && (dataLen > 0))
1244 wrqu.data.length = dataLen;
1246 wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1251 int RtmpOSNetDevAddrSet(
1252 IN PNET_DEV pNetDev,
1255 struct net_device *net_dev;
1259 GET_PAD_FROM_NET_DEV(pAd, net_dev);
1261 // work-around for the SuSE due to it has it's own interface name management system.
1263 NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1264 NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
1267 NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1275 * Assign the network dev name for created Ralink WiFi interface.
1277 static int RtmpOSNetDevRequestName(
1278 IN RTMP_ADAPTER *pAd,
1280 IN PSTRING pPrefixStr,
1283 PNET_DEV existNetDev;
1284 STRING suffixName[IFNAMSIZ];
1285 STRING desiredName[IFNAMSIZ];
1286 int ifNameIdx, prefixLen, slotNameLen;
1290 prefixLen = strlen(pPrefixStr);
1291 ASSERT((prefixLen < IFNAMSIZ));
1293 for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++)
1295 memset(suffixName, 0, IFNAMSIZ);
1296 memset(desiredName, 0, IFNAMSIZ);
1297 strncpy(&desiredName[0], pPrefixStr, prefixLen);
1299 sprintf(suffixName, "%d", ifNameIdx);
1301 slotNameLen = strlen(suffixName);
1302 ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1303 strcat(desiredName, suffixName);
1305 existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1306 if (existNetDev == NULL)
1309 RtmpOSNetDeviceRefPut(existNetDev);
1314 strcpy(&dev->name[0], &desiredName[0]);
1315 Status = NDIS_STATUS_SUCCESS;
1319 DBGPRINT(RT_DEBUG_ERROR,
1320 ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", pPrefixStr));
1321 Status = NDIS_STATUS_FAILURE;
1328 void RtmpOSNetDevClose(
1329 IN PNET_DEV pNetDev)
1335 void RtmpOSNetDevFree(PNET_DEV pNetDev)
1339 free_netdev(pNetDev);
1343 INT RtmpOSNetDevAlloc(
1344 IN PNET_DEV *new_dev_p,
1345 IN UINT32 privDataSize)
1347 // assign it as null first.
1350 DBGPRINT(RT_DEBUG_TRACE, ("Allocate a net device with private data size=%d!\n", privDataSize));
1351 *new_dev_p = alloc_etherdev(privDataSize);
1353 return NDIS_STATUS_SUCCESS;
1355 return NDIS_STATUS_FAILURE;
1359 PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName)
1361 PNET_DEV pTargetNetDev = NULL;
1363 pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1365 return pTargetNetDev;
1369 void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev)
1372 every time dev_get_by_name is called, and it has returned a valid struct
1373 net_device*, dev_put should be called afterwards, because otherwise the
1374 machine hangs when the device is unregistered (since dev->refcnt > 1).
1381 INT RtmpOSNetDevDestory(
1382 IN RTMP_ADAPTER *pAd,
1383 IN PNET_DEV pNetDev)
1386 // TODO: Need to fix this
1387 printk("WARNING: This function(%s) not implement yet!!!\n", __func__);
1392 void RtmpOSNetDevDetach(PNET_DEV pNetDev)
1394 unregister_netdev(pNetDev);
1398 int RtmpOSNetDevAttach(
1399 IN PNET_DEV pNetDev,
1400 IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook)
1402 int ret, rtnl_locked = FALSE;
1404 DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1405 // If we need hook some callback function to the net device structrue, now do it.
1408 PRTMP_ADAPTER pAd = NULL;
1410 GET_PAD_FROM_NET_DEV(pAd, pNetDev);
1412 pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1414 /* OS specific flags, here we used to indicate if we are virtual interface */
1415 pNetDev->priv_flags = pDevOpHook->priv_flags;
1418 if (pAd->OpMode == OPMODE_STA)
1420 pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1424 // copy the net device mac address to the net_device structure.
1425 NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN);
1427 rtnl_locked = pDevOpHook->needProtcted;
1431 ret = register_netdevice(pNetDev);
1433 ret = register_netdev(pNetDev);
1435 DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1437 return NDIS_STATUS_SUCCESS;
1439 return NDIS_STATUS_FAILURE;
1443 PNET_DEV RtmpOSNetDevCreate(
1444 IN RTMP_ADAPTER *pAd,
1448 IN PSTRING pNamePrefix)
1450 struct net_device *pNetDev = NULL;
1454 /* allocate a new network device */
1455 status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize*/);
1456 if (status != NDIS_STATUS_SUCCESS)
1458 /* allocation fail, exit */
1459 DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix));
1464 /* find a available interface name, max 32 interfaces */
1465 status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1466 if (status != NDIS_STATUS_SUCCESS)
1468 /* error! no any available ra name can be used! */
1469 DBGPRINT(RT_DEBUG_ERROR, ("Assign interface name (%s with suffix 0~32) failed...\n", pNamePrefix));
1470 RtmpOSNetDevFree(pNetDev);
1476 DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s...\n", pNamePrefix, pNetDev->name));