![Julia Lawall](/assets/img/avatar_default.png)
Drop cast on the result of kmalloc and similar functions. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // <smpl> @@ type T; @@ - (T *) (\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)) // </smpl> Signed-off-by: Julia Lawall <julia@diku.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1375 lines
36 KiB
C
1375 lines
36 KiB
C
/*
|
|
*************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 5F., No.36, Taiyuan St., Jhubei City,
|
|
* Hsinchu County 302,
|
|
* Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2007, Ralink Technology, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
*************************************************************************
|
|
*/
|
|
|
|
#include <linux/firmware.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
#include "rt_config.h"
|
|
|
|
unsigned long RTDebugLevel = RT_DEBUG_ERROR;
|
|
|
|
/* for wireless system event message */
|
|
char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
|
|
/* system status event */
|
|
"had associated successfully", /* IW_ASSOC_EVENT_FLAG */
|
|
"had disassociated", /* IW_DISASSOC_EVENT_FLAG */
|
|
"had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */
|
|
"had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */
|
|
"occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */
|
|
"occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
|
|
"occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */
|
|
"occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */
|
|
"occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */
|
|
"occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */
|
|
"Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
|
|
"Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
|
|
"RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
|
|
"set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
|
|
"set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
|
|
"connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */
|
|
"disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
|
|
"scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */
|
|
"scan terminate! Busy! Enqueue fail!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
|
|
};
|
|
|
|
/* for wireless IDS_spoof_attack event message */
|
|
char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
|
|
"detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */
|
|
"detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
|
|
"detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
|
|
"detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
|
|
"detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */
|
|
"detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */
|
|
"detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */
|
|
"detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */
|
|
"detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
|
|
"detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */
|
|
};
|
|
|
|
/* for wireless IDS_flooding_attack event message */
|
|
char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
|
|
"detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */
|
|
"detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
|
|
"detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
|
|
"detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
|
|
"detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */
|
|
"detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */
|
|
"detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
|
|
};
|
|
|
|
/* timeout -- ms */
|
|
void RTMP_SetPeriodicTimer(struct timer_list *pTimer,
|
|
IN unsigned long timeout)
|
|
{
|
|
timeout = ((timeout * OS_HZ) / 1000);
|
|
pTimer->expires = jiffies + timeout;
|
|
add_timer(pTimer);
|
|
}
|
|
|
|
/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
|
|
void RTMP_OS_Init_Timer(struct rt_rtmp_adapter *pAd,
|
|
struct timer_list *pTimer,
|
|
IN TIMER_FUNCTION function, void *data)
|
|
{
|
|
init_timer(pTimer);
|
|
pTimer->data = (unsigned long)data;
|
|
pTimer->function = function;
|
|
}
|
|
|
|
void RTMP_OS_Add_Timer(struct timer_list *pTimer,
|
|
IN unsigned long timeout)
|
|
{
|
|
if (timer_pending(pTimer))
|
|
return;
|
|
|
|
timeout = ((timeout * OS_HZ) / 1000);
|
|
pTimer->expires = jiffies + timeout;
|
|
add_timer(pTimer);
|
|
}
|
|
|
|
void RTMP_OS_Mod_Timer(struct timer_list *pTimer,
|
|
IN unsigned long timeout)
|
|
{
|
|
timeout = ((timeout * OS_HZ) / 1000);
|
|
mod_timer(pTimer, jiffies + timeout);
|
|
}
|
|
|
|
void RTMP_OS_Del_Timer(struct timer_list *pTimer,
|
|
OUT BOOLEAN * pCancelled)
|
|
{
|
|
if (timer_pending(pTimer)) {
|
|
*pCancelled = del_timer_sync(pTimer);
|
|
} else {
|
|
*pCancelled = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
void RTMP_OS_Release_Packet(struct rt_rtmp_adapter *pAd, struct rt_queue_entry *pEntry)
|
|
{
|
|
/*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */
|
|
}
|
|
|
|
/* Unify all delay routine by using udelay */
|
|
void RTMPusecDelay(unsigned long usec)
|
|
{
|
|
unsigned long i;
|
|
|
|
for (i = 0; i < (usec / 50); i++)
|
|
udelay(50);
|
|
|
|
if (usec % 50)
|
|
udelay(usec % 50);
|
|
}
|
|
|
|
void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
|
|
{
|
|
time->u.LowPart = jiffies;
|
|
}
|
|
|
|
/* pAd MUST allow to be NULL */
|
|
int os_alloc_mem(struct rt_rtmp_adapter *pAd, u8 ** mem, unsigned long size)
|
|
{
|
|
*mem = kmalloc(size, GFP_ATOMIC);
|
|
if (*mem)
|
|
return NDIS_STATUS_SUCCESS;
|
|
else
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
/* pAd MUST allow to be NULL */
|
|
int os_free_mem(struct rt_rtmp_adapter *pAd, void *mem)
|
|
{
|
|
|
|
ASSERT(mem);
|
|
kfree(mem);
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
void *RtmpOSNetPktAlloc(struct rt_rtmp_adapter *pAd, IN int size)
|
|
{
|
|
struct sk_buff *skb;
|
|
/* Add 2 more bytes for ip header alignment */
|
|
skb = dev_alloc_skb(size + 2);
|
|
|
|
return (void *)skb;
|
|
}
|
|
|
|
void *RTMP_AllocateFragPacketBuffer(struct rt_rtmp_adapter *pAd,
|
|
unsigned long Length)
|
|
{
|
|
struct sk_buff *pkt;
|
|
|
|
pkt = dev_alloc_skb(Length);
|
|
|
|
if (pkt == NULL) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("can't allocate frag rx %ld size packet\n", Length));
|
|
}
|
|
|
|
if (pkt) {
|
|
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
|
|
}
|
|
|
|
return (void *)pkt;
|
|
}
|
|
|
|
void *RTMP_AllocateTxPacketBuffer(struct rt_rtmp_adapter *pAd,
|
|
unsigned long Length,
|
|
IN BOOLEAN Cached,
|
|
void **VirtualAddress)
|
|
{
|
|
struct sk_buff *pkt;
|
|
|
|
pkt = dev_alloc_skb(Length);
|
|
|
|
if (pkt == NULL) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("can't allocate tx %ld size packet\n", Length));
|
|
}
|
|
|
|
if (pkt) {
|
|
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
|
|
*VirtualAddress = (void *)pkt->data;
|
|
} else {
|
|
*VirtualAddress = (void *)NULL;
|
|
}
|
|
|
|
return (void *)pkt;
|
|
}
|
|
|
|
void build_tx_packet(struct rt_rtmp_adapter *pAd,
|
|
void *pPacket,
|
|
u8 *pFrame, unsigned long FrameLen)
|
|
{
|
|
|
|
struct sk_buff *pTxPkt;
|
|
|
|
ASSERT(pPacket);
|
|
pTxPkt = RTPKT_TO_OSPKT(pPacket);
|
|
|
|
NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
|
|
}
|
|
|
|
void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
|
|
{
|
|
struct os_cookie *os_cookie;
|
|
int index;
|
|
|
|
os_cookie = (struct os_cookie *)pAd->OS_Cookie;
|
|
|
|
if (pAd->BeaconBuf)
|
|
kfree(pAd->BeaconBuf);
|
|
|
|
NdisFreeSpinLock(&pAd->MgmtRingLock);
|
|
|
|
#ifdef RTMP_MAC_PCI
|
|
NdisFreeSpinLock(&pAd->RxRingLock);
|
|
#ifdef RT3090
|
|
NdisFreeSpinLock(&pAd->McuCmdLock);
|
|
#endif /* RT3090 // */
|
|
#endif /* RTMP_MAC_PCI // */
|
|
|
|
for (index = 0; index < NUM_OF_TX_RING; index++) {
|
|
NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
|
|
NdisFreeSpinLock(&pAd->DeQueueLock[index]);
|
|
pAd->DeQueueRunning[index] = FALSE;
|
|
}
|
|
|
|
NdisFreeSpinLock(&pAd->irq_lock);
|
|
|
|
release_firmware(pAd->firmware);
|
|
|
|
vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
|
|
if (os_cookie)
|
|
kfree(os_cookie);
|
|
}
|
|
|
|
BOOLEAN OS_Need_Clone_Packet(void)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
|
|
must have only one NDIS BUFFER
|
|
return - byte copied. 0 means can't create NDIS PACKET
|
|
NOTE: internally created char should be destroyed by RTMPFreeNdisPacket
|
|
|
|
Arguments:
|
|
pAd Pointer to our adapter
|
|
pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
|
|
*pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet.
|
|
|
|
Return Value:
|
|
NDIS_STATUS_SUCCESS
|
|
NDIS_STATUS_FAILURE
|
|
|
|
Note:
|
|
|
|
========================================================================
|
|
*/
|
|
int RTMPCloneNdisPacket(struct rt_rtmp_adapter *pAd,
|
|
IN BOOLEAN pInsAMSDUHdr,
|
|
void *pInPacket,
|
|
void **ppOutPacket)
|
|
{
|
|
|
|
struct sk_buff *pkt;
|
|
|
|
ASSERT(pInPacket);
|
|
ASSERT(ppOutPacket);
|
|
|
|
/* 1. Allocate a packet */
|
|
pkt = dev_alloc_skb(2048);
|
|
|
|
if (pkt == NULL) {
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
|
|
NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket),
|
|
GET_OS_PKT_LEN(pInPacket));
|
|
*ppOutPacket = OSPKT_TO_RTPKT(pkt);
|
|
|
|
RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
|
|
|
|
printk("###Clone###\n");
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
/* the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() */
|
|
int RTMPAllocateNdisPacket(struct rt_rtmp_adapter *pAd,
|
|
void **ppPacket,
|
|
u8 *pHeader,
|
|
u32 HeaderLen,
|
|
u8 *pData, u32 DataLen)
|
|
{
|
|
void *pPacket;
|
|
ASSERT(pData);
|
|
ASSERT(DataLen);
|
|
|
|
/* 1. Allocate a packet */
|
|
pPacket =
|
|
(void **) dev_alloc_skb(HeaderLen + DataLen +
|
|
RTMP_PKT_TAIL_PADDING);
|
|
if (pPacket == NULL) {
|
|
*ppPacket = NULL;
|
|
#ifdef DEBUG
|
|
printk("RTMPAllocateNdisPacket Fail\n");
|
|
#endif
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
/* 2. clone the frame content */
|
|
if (HeaderLen > 0)
|
|
NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
|
|
if (DataLen > 0)
|
|
NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData,
|
|
DataLen);
|
|
|
|
/* 3. update length of packet */
|
|
skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen + DataLen);
|
|
|
|
RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
|
|
/* printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket)); */
|
|
*ppPacket = pPacket;
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
Description:
|
|
This routine frees a miniport internally allocated char and its
|
|
corresponding NDIS_BUFFER and allocated memory.
|
|
========================================================================
|
|
*/
|
|
void RTMPFreeNdisPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
|
|
{
|
|
dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
|
|
}
|
|
|
|
/* IRQL = DISPATCH_LEVEL */
|
|
/* NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same */
|
|
/* scatter gather buffer */
|
|
int Sniff2BytesFromNdisBuffer(char *pFirstBuffer,
|
|
u8 DesiredOffset,
|
|
u8 *pByte0, u8 *pByte1)
|
|
{
|
|
*pByte0 = *(u8 *)(pFirstBuffer + DesiredOffset);
|
|
*pByte1 = *(u8 *)(pFirstBuffer + DesiredOffset + 1);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
void RTMP_QueryPacketInfo(void *pPacket,
|
|
struct rt_packet_info *pPacketInfo,
|
|
u8 **pSrcBufVA, u32 * pSrcBufLen)
|
|
{
|
|
pPacketInfo->BufferCount = 1;
|
|
pPacketInfo->pFirstBuffer = (char *)GET_OS_PKT_DATAPTR(pPacket);
|
|
pPacketInfo->PhysicalBufferCount = 1;
|
|
pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
|
|
|
|
*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
|
|
*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
|
|
}
|
|
|
|
void RTMP_QueryNextPacketInfo(void **ppPacket,
|
|
struct rt_packet_info *pPacketInfo,
|
|
u8 **pSrcBufVA, u32 * pSrcBufLen)
|
|
{
|
|
void *pPacket = NULL;
|
|
|
|
if (*ppPacket)
|
|
pPacket = GET_OS_PKT_NEXT(*ppPacket);
|
|
|
|
if (pPacket) {
|
|
pPacketInfo->BufferCount = 1;
|
|
pPacketInfo->pFirstBuffer =
|
|
(char *)GET_OS_PKT_DATAPTR(pPacket);
|
|
pPacketInfo->PhysicalBufferCount = 1;
|
|
pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
|
|
|
|
*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
|
|
*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
|
|
*ppPacket = GET_OS_PKT_NEXT(pPacket);
|
|
} else {
|
|
pPacketInfo->BufferCount = 0;
|
|
pPacketInfo->pFirstBuffer = NULL;
|
|
pPacketInfo->PhysicalBufferCount = 0;
|
|
pPacketInfo->TotalPacketLength = 0;
|
|
|
|
*pSrcBufVA = NULL;
|
|
*pSrcBufLen = 0;
|
|
*ppPacket = NULL;
|
|
}
|
|
}
|
|
|
|
void *DuplicatePacket(struct rt_rtmp_adapter *pAd,
|
|
void *pPacket, u8 FromWhichBSSID)
|
|
{
|
|
struct sk_buff *skb;
|
|
void *pRetPacket = NULL;
|
|
u16 DataSize;
|
|
u8 *pData;
|
|
|
|
DataSize = (u16)GET_OS_PKT_LEN(pPacket);
|
|
pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
|
|
|
|
skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
|
|
if (skb) {
|
|
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pRetPacket = OSPKT_TO_RTPKT(skb);
|
|
}
|
|
|
|
return pRetPacket;
|
|
|
|
}
|
|
|
|
void *duplicate_pkt(struct rt_rtmp_adapter *pAd,
|
|
u8 *pHeader802_3,
|
|
u32 HdrLen,
|
|
u8 *pData,
|
|
unsigned long DataSize, u8 FromWhichBSSID)
|
|
{
|
|
struct sk_buff *skb;
|
|
void *pPacket = NULL;
|
|
|
|
skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG);
|
|
if (skb != NULL) {
|
|
skb_reserve(skb, 2);
|
|
NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
|
|
skb_put(skb, HdrLen);
|
|
NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
|
|
skb_put(skb, DataSize);
|
|
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pPacket = OSPKT_TO_RTPKT(skb);
|
|
}
|
|
|
|
return pPacket;
|
|
}
|
|
|
|
#define TKIP_TX_MIC_SIZE 8
|
|
void *duplicate_pkt_with_TKIP_MIC(struct rt_rtmp_adapter *pAd,
|
|
void *pPacket)
|
|
{
|
|
struct sk_buff *skb, *newskb;
|
|
|
|
skb = RTPKT_TO_OSPKT(pPacket);
|
|
if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) {
|
|
/* alloc a new skb and copy the packet */
|
|
newskb =
|
|
skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE,
|
|
GFP_ATOMIC);
|
|
dev_kfree_skb_any(skb);
|
|
if (newskb == NULL) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("Extend Tx.MIC for packet failed!, dropping packet!\n"));
|
|
return NULL;
|
|
}
|
|
skb = newskb;
|
|
}
|
|
|
|
return OSPKT_TO_RTPKT(skb);
|
|
}
|
|
|
|
void *ClonePacket(struct rt_rtmp_adapter *pAd,
|
|
void *pPacket,
|
|
u8 *pData, unsigned long DataSize)
|
|
{
|
|
struct sk_buff *pRxPkt;
|
|
struct sk_buff *pClonedPkt;
|
|
|
|
ASSERT(pPacket);
|
|
pRxPkt = RTPKT_TO_OSPKT(pPacket);
|
|
|
|
/* clone the packet */
|
|
pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
|
|
|
|
if (pClonedPkt) {
|
|
/* set the correct dataptr and data len */
|
|
pClonedPkt->dev = pRxPkt->dev;
|
|
pClonedPkt->data = pData;
|
|
pClonedPkt->len = DataSize;
|
|
skb_set_tail_pointer(pClonedPkt, DataSize)
|
|
ASSERT(DataSize < 1530);
|
|
}
|
|
return pClonedPkt;
|
|
}
|
|
|
|
/* */
|
|
/* change OS packet DataPtr and DataLen */
|
|
/* */
|
|
void update_os_packet_info(struct rt_rtmp_adapter *pAd,
|
|
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
|
|
{
|
|
struct sk_buff *pOSPkt;
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
|
|
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pOSPkt->data = pRxBlk->pData;
|
|
pOSPkt->len = pRxBlk->DataSize;
|
|
skb_set_tail_pointer(pOSPkt, pOSPkt->len);
|
|
}
|
|
|
|
void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
|
|
struct rt_rx_blk *pRxBlk,
|
|
u8 *pHeader802_3,
|
|
u8 FromWhichBSSID)
|
|
{
|
|
struct sk_buff *pOSPkt;
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
ASSERT(pHeader802_3);
|
|
|
|
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
|
|
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
|
|
pOSPkt->data = pRxBlk->pData;
|
|
pOSPkt->len = pRxBlk->DataSize;
|
|
skb_set_tail_pointer(pOSPkt, pOSPkt->len);
|
|
|
|
/* */
|
|
/* copy 802.3 header */
|
|
/* */
|
|
/* */
|
|
|
|
NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3,
|
|
LENGTH_802_3);
|
|
}
|
|
|
|
void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *pPacket)
|
|
{
|
|
|
|
struct sk_buff *pRxPkt;
|
|
|
|
ASSERT(pPacket);
|
|
|
|
pRxPkt = RTPKT_TO_OSPKT(pPacket);
|
|
|
|
/* Push up the protocol stack */
|
|
pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
|
|
|
|
netif_rx(pRxPkt);
|
|
}
|
|
|
|
struct rt_rtmp_sg_list *
|
|
rt_get_sg_list_from_packet(void *pPacket, struct rt_rtmp_sg_list *sg)
|
|
{
|
|
sg->NumberOfElements = 1;
|
|
sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
|
|
sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
|
|
return sg;
|
|
}
|
|
|
|
void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
|
|
{
|
|
unsigned char *pt;
|
|
int x;
|
|
|
|
if (RTDebugLevel < RT_DEBUG_TRACE)
|
|
return;
|
|
|
|
pt = pSrcBufVA;
|
|
printk("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen);
|
|
for (x = 0; x < SrcBufLen; x++) {
|
|
if (x % 16 == 0)
|
|
printk("0x%04x : ", x);
|
|
printk("%02x ", ((unsigned char)pt[x]));
|
|
if (x % 16 == 15)
|
|
printk("\n");
|
|
}
|
|
printk("\n");
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
Send log message through wireless event
|
|
|
|
Support standard iw_event with IWEVCUSTOM. It is used below.
|
|
|
|
iwreq_data.data.flags is used to store event_flag that is defined by user.
|
|
iwreq_data.data.length is the length of the event log.
|
|
|
|
The format of the event log is composed of the entry's MAC address and
|
|
the desired log message (refer to pWirelessEventText).
|
|
|
|
ex: 11:22:33:44:55:66 has associated successfully
|
|
|
|
p.s. The requirement of Wireless Extension is v15 or newer.
|
|
|
|
========================================================================
|
|
*/
|
|
void RTMPSendWirelessEvent(struct rt_rtmp_adapter *pAd,
|
|
u16 Event_flag,
|
|
u8 *pAddr, u8 BssIdx, char Rssi)
|
|
{
|
|
|
|
/*union iwreq_data wrqu; */
|
|
char *pBuf = NULL, *pBufPtr = NULL;
|
|
u16 event, type, BufLen;
|
|
u8 event_table_len = 0;
|
|
|
|
type = Event_flag & 0xFF00;
|
|
event = Event_flag & 0x00FF;
|
|
|
|
switch (type) {
|
|
case IW_SYS_EVENT_FLAG_START:
|
|
event_table_len = IW_SYS_EVENT_TYPE_NUM;
|
|
break;
|
|
|
|
case IW_SPOOF_EVENT_FLAG_START:
|
|
event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
|
|
break;
|
|
|
|
case IW_FLOOD_EVENT_FLAG_START:
|
|
event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
|
|
break;
|
|
}
|
|
|
|
if (event_table_len == 0) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s : The type(%0x02x) is not valid.\n", __func__,
|
|
type));
|
|
return;
|
|
}
|
|
|
|
if (event >= event_table_len) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s : The event(%0x02x) is not valid.\n", __func__,
|
|
event));
|
|
return;
|
|
}
|
|
/*Allocate memory and copy the msg. */
|
|
pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC);
|
|
if (pBuf != NULL) {
|
|
/*Prepare the payload */
|
|
memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
|
|
|
|
pBufPtr = pBuf;
|
|
|
|
if (pAddr)
|
|
pBufPtr +=
|
|
sprintf(pBufPtr,
|
|
"(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ",
|
|
PRINT_MAC(pAddr));
|
|
else if (BssIdx < MAX_MBSSID_NUM)
|
|
pBufPtr +=
|
|
sprintf(pBufPtr, "(RT2860) BSS(wlan%d) ", BssIdx);
|
|
else
|
|
pBufPtr += sprintf(pBufPtr, "(RT2860) ");
|
|
|
|
if (type == IW_SYS_EVENT_FLAG_START)
|
|
pBufPtr +=
|
|
sprintf(pBufPtr, "%s",
|
|
pWirelessSysEventText[event]);
|
|
else if (type == IW_SPOOF_EVENT_FLAG_START)
|
|
pBufPtr +=
|
|
sprintf(pBufPtr, "%s (RSSI=%d)",
|
|
pWirelessSpoofEventText[event], Rssi);
|
|
else if (type == IW_FLOOD_EVENT_FLAG_START)
|
|
pBufPtr +=
|
|
sprintf(pBufPtr, "%s",
|
|
pWirelessFloodEventText[event]);
|
|
else
|
|
pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
|
|
|
|
pBufPtr[pBufPtr - pBuf] = '\0';
|
|
BufLen = pBufPtr - pBuf;
|
|
|
|
RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL,
|
|
(u8 *)pBuf, BufLen);
|
|
/*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf)); */
|
|
|
|
kfree(pBuf);
|
|
} else
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s : Can't allocate memory for wireless event.\n",
|
|
__func__));
|
|
}
|
|
|
|
void send_monitor_packets(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
|
|
{
|
|
struct sk_buff *pOSPkt;
|
|
struct rt_wlan_ng_prism2_header *ph;
|
|
int rate_index = 0;
|
|
u16 header_len = 0;
|
|
u8 temp_header[40] = { 0 };
|
|
|
|
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 */
|
|
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,
|
|
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
|
|
};
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
if (pRxBlk->DataSize < 10) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s : Size is too small! (%d)\n", __func__,
|
|
pRxBlk->DataSize));
|
|
goto err_free_sk_buff;
|
|
}
|
|
|
|
if (pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header) >
|
|
RX_BUFFER_AGGRESIZE) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s : Size is too large! (%zu)\n", __func__,
|
|
pRxBlk->DataSize + sizeof(struct rt_wlan_ng_prism2_header)));
|
|
goto err_free_sk_buff;
|
|
}
|
|
|
|
pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
|
|
if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) {
|
|
pRxBlk->DataSize -= LENGTH_802_11;
|
|
if ((pRxBlk->pHeader->FC.ToDs == 1) &&
|
|
(pRxBlk->pHeader->FC.FrDs == 1))
|
|
header_len = LENGTH_802_11_WITH_ADDR4;
|
|
else
|
|
header_len = LENGTH_802_11;
|
|
|
|
/* QOS */
|
|
if (pRxBlk->pHeader->FC.SubType & 0x08) {
|
|
header_len += 2;
|
|
/* Data skip QOS contorl field */
|
|
pRxBlk->DataSize -= 2;
|
|
}
|
|
/* Order bit: A-Ralink or HTC+ */
|
|
if (pRxBlk->pHeader->FC.Order) {
|
|
header_len += 4;
|
|
/* Data skip HTC contorl field */
|
|
pRxBlk->DataSize -= 4;
|
|
}
|
|
/* Copy Header */
|
|
if (header_len <= 40)
|
|
NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
|
|
|
|
/* skip HW padding */
|
|
if (pRxBlk->RxD.L2PAD)
|
|
pRxBlk->pData += (header_len + 2);
|
|
else
|
|
pRxBlk->pData += header_len;
|
|
} /*end if */
|
|
|
|
if (pRxBlk->DataSize < pOSPkt->len) {
|
|
skb_trim(pOSPkt, pRxBlk->DataSize);
|
|
} else {
|
|
skb_put(pOSPkt, (pRxBlk->DataSize - pOSPkt->len));
|
|
} /*end if */
|
|
|
|
if ((pRxBlk->pData - pOSPkt->data) > 0) {
|
|
skb_put(pOSPkt, (pRxBlk->pData - pOSPkt->data));
|
|
skb_pull(pOSPkt, (pRxBlk->pData - pOSPkt->data));
|
|
} /*end if */
|
|
|
|
if (skb_headroom(pOSPkt) < (sizeof(struct rt_wlan_ng_prism2_header) + header_len)) {
|
|
if (pskb_expand_head
|
|
(pOSPkt, (sizeof(struct rt_wlan_ng_prism2_header) + header_len), 0,
|
|
GFP_ATOMIC)) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s : Reallocate header size of sk_buff fail!\n",
|
|
__func__));
|
|
goto err_free_sk_buff;
|
|
} /*end if */
|
|
} /*end if */
|
|
|
|
if (header_len > 0)
|
|
NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
|
|
header_len);
|
|
|
|
ph = (struct rt_wlan_ng_prism2_header *)skb_push(pOSPkt,
|
|
sizeof(struct rt_wlan_ng_prism2_header));
|
|
NdisZeroMemory(ph, sizeof(struct rt_wlan_ng_prism2_header));
|
|
|
|
ph->msgcode = DIDmsg_lnxind_wlansniffrm;
|
|
ph->msglen = sizeof(struct rt_wlan_ng_prism2_header);
|
|
strcpy((char *)ph->devname, (char *)pAd->net_dev->name);
|
|
|
|
ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
|
|
ph->hosttime.status = 0;
|
|
ph->hosttime.len = 4;
|
|
ph->hosttime.data = jiffies;
|
|
|
|
ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
|
|
ph->mactime.status = 0;
|
|
ph->mactime.len = 0;
|
|
ph->mactime.data = 0;
|
|
|
|
ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
|
|
ph->istx.status = 0;
|
|
ph->istx.len = 0;
|
|
ph->istx.data = 0;
|
|
|
|
ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
|
|
ph->channel.status = 0;
|
|
ph->channel.len = 4;
|
|
|
|
ph->channel.data = (u_int32_t) pAd->CommonCfg.Channel;
|
|
|
|
ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
|
|
ph->rssi.status = 0;
|
|
ph->rssi.len = 4;
|
|
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));;
|
|
|
|
ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
|
|
ph->signal.status = 0;
|
|
ph->signal.len = 4;
|
|
ph->signal.data = 0; /*rssi + noise; */
|
|
|
|
ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
|
|
ph->noise.status = 0;
|
|
ph->noise.len = 4;
|
|
ph->noise.data = 0;
|
|
|
|
if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) {
|
|
rate_index =
|
|
16 + ((u8)pRxBlk->pRxWI->BW * 16) +
|
|
((u8)pRxBlk->pRxWI->ShortGI * 32) +
|
|
((u8)pRxBlk->pRxWI->MCS);
|
|
} else if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
|
|
rate_index = (u8)(pRxBlk->pRxWI->MCS) + 4;
|
|
else
|
|
rate_index = (u8)(pRxBlk->pRxWI->MCS);
|
|
if (rate_index < 0)
|
|
rate_index = 0;
|
|
if (rate_index > 255)
|
|
rate_index = 255;
|
|
|
|
ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
|
|
ph->rate.status = 0;
|
|
ph->rate.len = 4;
|
|
ph->rate.data = ralinkrate[rate_index];
|
|
|
|
ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
|
|
ph->frmlen.status = 0;
|
|
ph->frmlen.len = 4;
|
|
ph->frmlen.data = (u_int32_t) pRxBlk->DataSize;
|
|
|
|
pOSPkt->pkt_type = PACKET_OTHERHOST;
|
|
pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
|
|
pOSPkt->ip_summed = CHECKSUM_NONE;
|
|
netif_rx(pOSPkt);
|
|
|
|
return;
|
|
|
|
err_free_sk_buff:
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
|
|
return;
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
|
|
Device IRQ related functions.
|
|
|
|
*******************************************************************************/
|
|
int RtmpOSIRQRequest(struct net_device *pNetDev)
|
|
{
|
|
#ifdef RTMP_PCI_SUPPORT
|
|
struct net_device *net_dev = pNetDev;
|
|
struct rt_rtmp_adapter *pAd = NULL;
|
|
int retval = 0;
|
|
|
|
GET_PAD_FROM_NET_DEV(pAd, pNetDev);
|
|
|
|
ASSERT(pAd);
|
|
|
|
if (pAd->infType == RTMP_DEV_INF_PCI) {
|
|
struct os_cookie *_pObj = (struct os_cookie *)(pAd->OS_Cookie);
|
|
RTMP_MSI_ENABLE(pAd);
|
|
retval =
|
|
request_irq(_pObj->pci_dev->irq, rt2860_interrupt, SA_SHIRQ,
|
|
(net_dev)->name, (net_dev));
|
|
if (retval != 0)
|
|
printk("RT2860: request_irq ERROR(%d)\n", retval);
|
|
}
|
|
|
|
return retval;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int RtmpOSIRQRelease(struct net_device *pNetDev)
|
|
{
|
|
struct net_device *net_dev = pNetDev;
|
|
struct rt_rtmp_adapter *pAd = NULL;
|
|
|
|
GET_PAD_FROM_NET_DEV(pAd, net_dev);
|
|
|
|
ASSERT(pAd);
|
|
|
|
#ifdef RTMP_PCI_SUPPORT
|
|
if (pAd->infType == RTMP_DEV_INF_PCI) {
|
|
struct os_cookie *pObj = (struct os_cookie *)(pAd->OS_Cookie);
|
|
synchronize_irq(pObj->pci_dev->irq);
|
|
free_irq(pObj->pci_dev->irq, (net_dev));
|
|
RTMP_MSI_DISABLE(pAd);
|
|
}
|
|
#endif /* RTMP_PCI_SUPPORT // */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
|
|
File open/close related functions.
|
|
|
|
*******************************************************************************/
|
|
struct file *RtmpOSFileOpen(char *pPath, int flag, int mode)
|
|
{
|
|
struct file *filePtr;
|
|
|
|
filePtr = filp_open(pPath, flag, 0);
|
|
if (IS_ERR(filePtr)) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s(): Error %ld opening %s\n", __func__,
|
|
-PTR_ERR(filePtr), pPath));
|
|
}
|
|
|
|
return (struct file *)filePtr;
|
|
}
|
|
|
|
int RtmpOSFileClose(struct file *osfd)
|
|
{
|
|
filp_close(osfd, NULL);
|
|
return 0;
|
|
}
|
|
|
|
void RtmpOSFileSeek(struct file *osfd, int offset)
|
|
{
|
|
osfd->f_pos = offset;
|
|
}
|
|
|
|
int RtmpOSFileRead(struct file *osfd, char *pDataPtr, int readLen)
|
|
{
|
|
/* The object must have a read method */
|
|
if (osfd->f_op && osfd->f_op->read) {
|
|
return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int RtmpOSFileWrite(struct file *osfd, char *pDataPtr, int writeLen)
|
|
{
|
|
return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen,
|
|
&osfd->f_pos);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
|
|
Task create/management/kill related functions.
|
|
|
|
*******************************************************************************/
|
|
int RtmpOSTaskKill(struct rt_rtmp_os_task *pTask)
|
|
{
|
|
struct rt_rtmp_adapter *pAd;
|
|
int ret = NDIS_STATUS_FAILURE;
|
|
|
|
pAd = (struct rt_rtmp_adapter *)pTask->priv;
|
|
|
|
#ifdef KTHREAD_SUPPORT
|
|
if (pTask->kthread_task) {
|
|
kthread_stop(pTask->kthread_task);
|
|
ret = NDIS_STATUS_SUCCESS;
|
|
}
|
|
#else
|
|
CHECK_PID_LEGALITY(pTask->taskPID) {
|
|
printk("Terminate the task(%s) with pid(%d)!\n",
|
|
pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
|
|
mb();
|
|
pTask->task_killed = 1;
|
|
mb();
|
|
ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
|
|
if (ret) {
|
|
printk(KERN_WARNING
|
|
"kill task(%s) with pid(%d) failed(retVal=%d)!\n",
|
|
pTask->taskName, GET_PID_NUMBER(pTask->taskPID),
|
|
ret);
|
|
} else {
|
|
wait_for_completion(&pTask->taskComplete);
|
|
pTask->taskPID = THREAD_PID_INIT_VALUE;
|
|
pTask->task_killed = 0;
|
|
ret = NDIS_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
int RtmpOSTaskNotifyToExit(struct rt_rtmp_os_task *pTask)
|
|
{
|
|
|
|
#ifndef KTHREAD_SUPPORT
|
|
complete_and_exit(&pTask->taskComplete, 0);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void RtmpOSTaskCustomize(struct rt_rtmp_os_task *pTask)
|
|
{
|
|
|
|
#ifndef KTHREAD_SUPPORT
|
|
|
|
daemonize((char *)&pTask->taskName[0] /*"%s",pAd->net_dev->name */);
|
|
|
|
allow_signal(SIGTERM);
|
|
allow_signal(SIGKILL);
|
|
current->flags |= PF_NOFREEZE;
|
|
|
|
/* signal that we've started the thread */
|
|
complete(&pTask->taskComplete);
|
|
|
|
#endif
|
|
}
|
|
|
|
int RtmpOSTaskAttach(struct rt_rtmp_os_task *pTask,
|
|
IN int (*fn) (void *), IN void *arg)
|
|
{
|
|
int status = NDIS_STATUS_SUCCESS;
|
|
|
|
#ifdef KTHREAD_SUPPORT
|
|
pTask->task_killed = 0;
|
|
pTask->kthread_task = NULL;
|
|
pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
|
|
if (IS_ERR(pTask->kthread_task))
|
|
status = NDIS_STATUS_FAILURE;
|
|
#else
|
|
pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
|
|
if (pid_number < 0) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("Attach task(%s) failed!\n", pTask->taskName));
|
|
status = NDIS_STATUS_FAILURE;
|
|
} else {
|
|
pTask->taskPID = GET_PID(pid_number);
|
|
|
|
/* Wait for the thread to start */
|
|
wait_for_completion(&pTask->taskComplete);
|
|
status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
#endif
|
|
return status;
|
|
}
|
|
|
|
int RtmpOSTaskInit(struct rt_rtmp_os_task *pTask,
|
|
char *pTaskName, void * pPriv)
|
|
{
|
|
int len;
|
|
|
|
ASSERT(pTask);
|
|
|
|
#ifndef KTHREAD_SUPPORT
|
|
NdisZeroMemory((u8 *)(pTask), sizeof(struct rt_rtmp_os_task));
|
|
#endif
|
|
|
|
len = strlen(pTaskName);
|
|
len =
|
|
len >
|
|
(RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len;
|
|
NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
|
|
pTask->priv = pPriv;
|
|
|
|
#ifndef KTHREAD_SUPPORT
|
|
RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
|
|
pTask->taskPID = THREAD_PID_INIT_VALUE;
|
|
|
|
init_completion(&pTask->taskComplete);
|
|
#endif
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
void RTMP_IndicateMediaState(struct rt_rtmp_adapter *pAd)
|
|
{
|
|
if (pAd->CommonCfg.bWirelessEvent) {
|
|
if (pAd->IndicateMediaState == NdisMediaStateConnected) {
|
|
RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
|
|
pAd->MacTab.Content[BSSID_WCID].
|
|
Addr, BSS0, 0);
|
|
} else {
|
|
RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
|
|
pAd->MacTab.Content[BSSID_WCID].
|
|
Addr, BSS0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
int RtmpOSWrielessEventSend(struct rt_rtmp_adapter *pAd,
|
|
u32 eventType,
|
|
int flags,
|
|
u8 *pSrcMac,
|
|
u8 *pData, u32 dataLen)
|
|
{
|
|
union iwreq_data wrqu;
|
|
|
|
memset(&wrqu, 0, sizeof(wrqu));
|
|
|
|
if (flags > -1)
|
|
wrqu.data.flags = flags;
|
|
|
|
if (pSrcMac)
|
|
memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
|
|
|
|
if ((pData != NULL) && (dataLen > 0))
|
|
wrqu.data.length = dataLen;
|
|
|
|
wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
|
|
return 0;
|
|
}
|
|
|
|
int RtmpOSNetDevAddrSet(struct net_device *pNetDev, u8 *pMacAddr)
|
|
{
|
|
struct net_device *net_dev;
|
|
struct rt_rtmp_adapter *pAd;
|
|
|
|
net_dev = pNetDev;
|
|
GET_PAD_FROM_NET_DEV(pAd, net_dev);
|
|
|
|
/* work-around for the SuSE due to it has it's own interface name management system. */
|
|
{
|
|
NdisZeroMemory(pAd->StaCfg.dev_name, 16);
|
|
NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name,
|
|
strlen(net_dev->name));
|
|
}
|
|
|
|
NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Assign the network dev name for created Ralink WiFi interface.
|
|
*/
|
|
static int RtmpOSNetDevRequestName(struct rt_rtmp_adapter *pAd,
|
|
struct net_device *dev,
|
|
char *pPrefixStr, int devIdx)
|
|
{
|
|
struct net_device *existNetDev;
|
|
char suffixName[IFNAMSIZ];
|
|
char desiredName[IFNAMSIZ];
|
|
int ifNameIdx, prefixLen, slotNameLen;
|
|
int Status;
|
|
|
|
prefixLen = strlen(pPrefixStr);
|
|
ASSERT((prefixLen < IFNAMSIZ));
|
|
|
|
for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) {
|
|
memset(suffixName, 0, IFNAMSIZ);
|
|
memset(desiredName, 0, IFNAMSIZ);
|
|
strncpy(&desiredName[0], pPrefixStr, prefixLen);
|
|
|
|
sprintf(suffixName, "%d", ifNameIdx);
|
|
|
|
slotNameLen = strlen(suffixName);
|
|
ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
|
|
strcat(desiredName, suffixName);
|
|
|
|
existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
|
|
if (existNetDev == NULL)
|
|
break;
|
|
else
|
|
RtmpOSNetDeviceRefPut(existNetDev);
|
|
}
|
|
|
|
if (ifNameIdx < 32) {
|
|
strcpy(&dev->name[0], &desiredName[0]);
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n",
|
|
pPrefixStr));
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
void RtmpOSNetDevClose(struct net_device *pNetDev)
|
|
{
|
|
dev_close(pNetDev);
|
|
}
|
|
|
|
void RtmpOSNetDevFree(struct net_device *pNetDev)
|
|
{
|
|
ASSERT(pNetDev);
|
|
|
|
free_netdev(pNetDev);
|
|
}
|
|
|
|
int RtmpOSNetDevAlloc(struct net_device **new_dev_p, u32 privDataSize)
|
|
{
|
|
/* assign it as null first. */
|
|
*new_dev_p = NULL;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Allocate a net device with private data size=%d!\n",
|
|
privDataSize));
|
|
*new_dev_p = alloc_etherdev(privDataSize);
|
|
if (*new_dev_p)
|
|
return NDIS_STATUS_SUCCESS;
|
|
else
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
struct net_device *RtmpOSNetDevGetByName(struct net_device *pNetDev, char *pDevName)
|
|
{
|
|
struct net_device *pTargetNetDev = NULL;
|
|
|
|
pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
|
|
|
|
return pTargetNetDev;
|
|
}
|
|
|
|
void RtmpOSNetDeviceRefPut(struct net_device *pNetDev)
|
|
{
|
|
/*
|
|
every time dev_get_by_name is called, and it has returned a valid struct
|
|
net_device*, dev_put should be called afterwards, because otherwise the
|
|
machine hangs when the device is unregistered (since dev->refcnt > 1).
|
|
*/
|
|
if (pNetDev)
|
|
dev_put(pNetDev);
|
|
}
|
|
|
|
int RtmpOSNetDevDestory(struct rt_rtmp_adapter *pAd, struct net_device *pNetDev)
|
|
{
|
|
|
|
/* TODO: Need to fix this */
|
|
printk("WARNING: This function(%s) not implement yet!\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
void RtmpOSNetDevDetach(struct net_device *pNetDev)
|
|
{
|
|
unregister_netdev(pNetDev);
|
|
}
|
|
|
|
int RtmpOSNetDevAttach(struct net_device *pNetDev,
|
|
struct rt_rtmp_os_netdev_op_hook *pDevOpHook)
|
|
{
|
|
int ret, rtnl_locked = FALSE;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
|
|
/* If we need hook some callback function to the net device structrue, now do it. */
|
|
if (pDevOpHook) {
|
|
struct rt_rtmp_adapter *pAd = NULL;
|
|
|
|
GET_PAD_FROM_NET_DEV(pAd, pNetDev);
|
|
|
|
pNetDev->netdev_ops = pDevOpHook->netdev_ops;
|
|
|
|
/* OS specific flags, here we used to indicate if we are virtual interface */
|
|
pNetDev->priv_flags = pDevOpHook->priv_flags;
|
|
|
|
if (pAd->OpMode == OPMODE_STA) {
|
|
pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
|
|
}
|
|
|
|
/* copy the net device mac address to the net_device structure. */
|
|
NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0],
|
|
MAC_ADDR_LEN);
|
|
|
|
rtnl_locked = pDevOpHook->needProtcted;
|
|
}
|
|
|
|
if (rtnl_locked)
|
|
ret = register_netdevice(pNetDev);
|
|
else
|
|
ret = register_netdev(pNetDev);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
|
|
if (ret == 0)
|
|
return NDIS_STATUS_SUCCESS;
|
|
else
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
struct net_device *RtmpOSNetDevCreate(struct rt_rtmp_adapter *pAd,
|
|
int devType,
|
|
int devNum,
|
|
int privMemSize, char *pNamePrefix)
|
|
{
|
|
struct net_device *pNetDev = NULL;
|
|
int status;
|
|
|
|
/* allocate a new network device */
|
|
status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */);
|
|
if (status != NDIS_STATUS_SUCCESS) {
|
|
/* allocation fail, exit */
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("Allocate network device fail (%s)...\n",
|
|
pNamePrefix));
|
|
return NULL;
|
|
}
|
|
|
|
/* find a available interface name, max 32 interfaces */
|
|
status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
|
|
if (status != NDIS_STATUS_SUCCESS) {
|
|
/* error! no any available ra name can be used! */
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("Assign interface name (%s with suffix 0~32) failed...\n",
|
|
pNamePrefix));
|
|
RtmpOSNetDevFree(pNetDev);
|
|
|
|
return NULL;
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("The name of the new %s interface is %s...\n",
|
|
pNamePrefix, pNetDev->name));
|
|
}
|
|
|
|
return pNetDev;
|
|
}
|