📄 rtusb_main.c
字号:
/*************************************************************************** * RT2x00 SourceForge Project - http://rt2x00.sourceforge.net * * * * 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. * * * * Licensed under the GNU GPL * * Original code supplied under license from RaLink Inc, 2004. * ***************************************************************************//*************************************************************************** * Module Name: rtusb_main.c * * Abstract: * * Revision History: * Who When What * -------- ---------- ------------------------------- * Name Date Modification logs * Jan Lee 2005-06-01 Release * RobinC 02-06-2005 usb_kill_urb fixes for kernels =>2.6.7 ***************************************************************************/#include "rt_config.h"#include <linux/ethtool.h>unsigned long flagg;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)ULONG debug = RT_DEBUG_OFF;MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Enable level: accepted values: 1 to switch debug on, 0 to switch debug off.");#elseULONG debug = RT_DEBUG_OFF;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Enable level: accepted values: 1 to switch debug on, 0 to switch debug off.");#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */#define KERNEL_20424 0x20418#define KERNEL_20418 0x20412#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)/* Kernel thread and vars, which handles packets that are completed. Only * packets that have a "complete" function are sent here. This way, the * completion is run out of kernel context, and doesn't block the rest of * the stack. */static int mlme_kill;static int RTUSBCmd_kill;#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) */extern const struct iw_handler_def rt2500usb_iw_handler_def;static struct usb_device_id rtusb_usb_id[] = RTUSB_DEVICES;/* the number of entries in array above */int const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);#ifndef PF_NOFREEZE#define PF_NOFREEZE 0#endif/* * Register layout information. */#define CSR_REG_BASE 0x0400#define CSR_REG_SIZE 0x00ff#define EEPROM_BASE 0x0000#define EEPROM_SIZE 0x006a#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)static voidrt2x00_get_drvinfo(struct net_device *net_dev, struct ethtool_drvinfo *drvinfo){ PRT2570ADAPTER pAd = net_dev->priv; strcpy(drvinfo->driver, NIC_DEVICE_NAME); strcpy(drvinfo->version, DRV_VERSION); strcpy(drvinfo->bus_info, pAd->usb->dev.bus_id);}static intrt2x00_get_regs_len(struct net_device *net_dev){ return CSR_REG_SIZE;}static voidrt2x00_get_regs(struct net_device *net_dev, struct ethtool_regs *regs, void *data){ PRT2570ADAPTER pAd = net_dev->priv; unsigned int counter; regs->len = CSR_REG_SIZE; for (counter = 0; counter < CSR_REG_SIZE; counter += sizeof(u16)) { RTUSBReadMACRegister(pAd, CSR_REG_BASE + counter, (u16*)data); data += sizeof(u16); }}static intrt2x00_get_eeprom_len(struct net_device *net_dev){ return EEPROM_SIZE;}static intrt2x00_get_eeprom(struct net_device *net_dev, struct ethtool_eeprom *eeprom, u8 *data){ PRT2570ADAPTER pAd = net_dev->priv; RTUSBReadEEPROM(pAd, CSR_REG_BASE, data, eeprom->len); return 0;}static struct ethtool_ops rt2x00_ethtool_ops = { .get_drvinfo = rt2x00_get_drvinfo, .get_regs_len = rt2x00_get_regs_len, .get_regs = rt2x00_get_regs, .get_link = ethtool_op_get_link, .get_eeprom_len = rt2x00_get_eeprom_len, .get_eeprom = rt2x00_get_eeprom,};#endif/**************************************************************************//**************************************************************************///tested for kernel 2.4 series/**************************************************************************//**************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static void usb_rtusb_disconnect(struct usb_device *dev, void *ptr);static void *usb_rtusb_probe(struct usb_device *dev, UINT interface, const struct usb_device_id *id_table);struct usb_driver rtusb_driver = { name:"rt2500usb", probe:usb_rtusb_probe, disconnect:usb_rtusb_disconnect, id_table:rtusb_usb_id, };#else/**************************************************************************//**************************************************************************///tested for kernel 2.6series/**************************************************************************//**************************************************************************/static int usb_rtusb_probe (struct usb_interface *intf, const struct usb_device_id *id);static void usb_rtusb_disconnect(struct usb_interface *intf);struct usb_driver rtusb_driver = {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) .owner = THIS_MODULE,#endif .name="rt2570", .probe=usb_rtusb_probe, .disconnect=usb_rtusb_disconnect, .id_table=rtusb_usb_id, };#endif//static void USB_RxPacketComplete_bh(unsigned long data)//{// RTUSBRxPacket(data);//}#if 0#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)static inline unsigned int jiffies_to_msecs(const unsigned long j){#if HZ <= 1000 && !(1000 % HZ) return (1000 / HZ) * j;#elif HZ > 1000 && !(HZ % 1000) return (j + (HZ / 1000) - 1)/(HZ / 1000);#else return (j * 1000) / HZ;#endif}static inline unsigned long msecs_to_jiffies(const unsigned int m){ if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET)) return MAX_JIFFY_OFFSET;#if HZ <= 1000 && !(1000 % HZ) return (m + (1000 / HZ) - 1) / (1000 / HZ);#elif HZ > 1000 && !(HZ % 1000) return m * (HZ / 1000); #else return (m * HZ + 999) / 1000; #endif}/*** msleep - sleep safely even with waitqueue interruptions* @msecs: Time in milliseconds to sleep for*/ void msleep(unsigned int msecs){ unsigned long timeout = msecs_to_jiffies(msecs) + 1; while (timeout) { set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout(timeout); }}#endifstruct net_device_stats *rt_getstats(struct net_device *dev){ PRT2570ADAPTER pAd = (PRT2570ADAPTER)dev->priv; struct net_device_stats *stats= &pAd->net_device_stats; stats->rx_bytes = pAd->RalinkCounters.ReceivedByteCount; stats->rx_packets = pAd->Counters.GoodReceives; stats->rx_errors = pAd->Counters.RxErrors; stats->tx_bytes = pAd->RalinkCounters.TransmittedByteCount; stats->tx_packets = pAd->Counters.GoodTransmits; stats->tx_errors = pAd->Counters.TxErrors; return stats;}#if WIRELESS_EXT >= 12/* ======================================================================== Routine Description: get wireless statistics Arguments: net_dev Pointer to net_device Return Value: struct iw_statistics Note: This function will be called when query /proc ========================================================================*/struct iw_statistics *RTUSB_get_wireless_stats( IN struct net_device *net_dev){ PRT2570ADAPTER pAd = (PRT2570ADAPTER)net_dev->priv; DBGPRINT(RT_DEBUG_TRACE, "--->RTUSB_get_wireless_stats \n"); // TODO: All elements are zero before be implemented pAd->iw_stats.status = 0; // Status - device dependent for now pAd->iw_stats.qual.qual = pAd->Mlme.ChannelQuality;//pAd->Mlme.RoamCqi; // link quality (%retries, SNR, %missed beacons or better...) pAd->iw_stats.qual.level = pAd->PortCfg.LastRssi - RSSI_TO_DBM_OFFSET; // signal level (dBm) pAd->iw_stats.qual.noise = (pAd->PortCfg.LastR17Value > BBP_R17_DYNAMIC_UP_BOUND) ? BBP_R17_DYNAMIC_UP_BOUND : ((ULONG) pAd->PortCfg.LastR17Value); // noise level (dBm) pAd->iw_stats.qual.updated = 1; // Flags to know if updated pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe // pAd->iw_stats.discard.code, discard.fragment, discard.retries, discard.misc has counted in other place return &pAd->iw_stats;}#endifint rt2570_set_mac_address(struct net_device *net_dev, void *addr){ RT2570ADAPTER *pAd = net_dev->priv; struct sockaddr *mac = (struct sockaddr*) addr; if(netif_running(net_dev)) return -EBUSY; if(!is_valid_ether_addr(&mac->sa_data[0])) return -EINVAL;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) BUG_ON(net_dev->addr_len != ETH_ALEN);#endif memcpy(net_dev->dev_addr, mac->sa_data, ETH_ALEN); memcpy(&pAd->CurrentAddress, &mac->sa_data, ETH_ALEN); printk(KERN_INFO "***rt2x00***: Info - Mac address changed to: %02x:%02x:%02x:%02x:%02x:%02x.\n", net_dev->dev_addr[0], net_dev->dev_addr[1], net_dev->dev_addr[2], net_dev->dev_addr[3], net_dev->dev_addr[4], net_dev->dev_addr[5]); return RTUSBWriteHWMACAddress(pAd);}VOID RTUSBHalt( IN PRT2570ADAPTER pAdapter, BOOLEAN IsFree){ MLME_DISASSOC_REQ_STRUCT DisReq; MLME_QUEUE_ELEM MsgElem; DBGPRINT(RT_DEBUG_TRACE, "====> RTUSBHalt\n"); // before set flag fRTMP_ADAPTER_HALT_IN_PROGRESS, // we should send a disassoc frame to our AP. //#if 1 if (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS)) { if (INFRA_ON(pAdapter)) { COPY_MAC_ADDR(&DisReq.Addr, &pAdapter->PortCfg.Bssid); DisReq.Reason = REASON_DISASSOC_STA_LEAVING; MsgElem.Machine = ASSOC_STATE_MACHINE; MsgElem.MsgType = MT2_MLME_DISASSOC_REQ; MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); memcpy(MsgElem.Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); MlmeDisassocReqAction(pAdapter, &MsgElem); NdisMSleep(1000); } // disable BEACON generation and other BEACON related hardware timers AsicDisableSync(pAdapter); }#endif RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS); RTUSBCleanUpMLMEWaitQueue(pAdapter); RTUSBCleanUpMLMEBulkOutQueue(pAdapter); // Free MLME stuff MlmeHalt(pAdapter); ReleaseAdapter(pAdapter, IsFree); RTMP_CLEAR_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS);}VOID CMDHandler( IN PRT2570ADAPTER pAdapter) { PCmdQElmt cmdqelmt; PUCHAR pData; NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; while (pAdapter->CmdQ.size > 0) { NdisStatus = NDIS_STATUS_SUCCESS; NdisAcquireSpinLock(&pAdapter->CmdQLock); RTUSBDequeueCmd(&pAdapter->CmdQ, &cmdqelmt); NdisReleaseSpinLock(&pAdapter->CmdQLock); if (cmdqelmt == NULL) break; pData = cmdqelmt->buffer; switch (cmdqelmt->command) { case RT_OID_CHECK_GPIO: { USHORT data; // Read GPIO pin0 as Hardware controlled radio state RTUSBReadMACRegister(pAdapter, MAC_CSR19, &data); if (data & 0x80) { pAdapter->PortCfg.bHwRadio = TRUE; } else { pAdapter->PortCfg.bHwRadio = FALSE; } if (pAdapter->PortCfg.bRadio != (pAdapter->PortCfg.bHwRadio && pAdapter->PortCfg.bSwRadio)) { pAdapter->PortCfg.bRadio = (pAdapter->PortCfg.bHwRadio && pAdapter->PortCfg.bSwRadio); if (pAdapter->PortCfg.bRadio == TRUE) { MlmeRadioOn(pAdapter); // Update extra information pAdapter->ExtraInfo = EXTRA_INFO_CLEAR; } else { MlmeRadioOff(pAdapter); // Update extra information pAdapter->ExtraInfo = HW_RADIO_OFF; } } } break; case RT_OID_PERIODIC_EXECUT: PeriodicExec(pAdapter); break; case OID_802_11_BSSID_LIST_SCAN: { if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! MLME busy (Line#%d)!!!\n", __LINE__); MlmeRestartStateMachine(pAdapter); MlmePostRestartStateMachine(pAdapter); } //Now = jiffies; pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE; // Reset Missed scan number pAdapter->PortCfg.IgnoredScanNumber = 0; //pAdapter->PortCfg.LastScanTime = Now; MlmeEnqueue(pAdapter, MLME_CNTL_STATE_MACHINE, OID_802_11_BSSID_LIST_SCAN, 0, NULL); RTUSBUp(pAdapter, &pAdapter->mlme_semaphore); } break; case RT_OID_802_11_BSSID: { if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! MLME busy (Line#%d)!!!\n", __LINE__); MlmeRestartStateMachine(pAdapter); MlmePostRestartStateMachine(pAdapter); } pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE; // Reset allowed scan retries pAdapter->PortCfg.IgnoredScanNumber = 0; MlmeEnqueue(pAdapter, MLME_CNTL_STATE_MACHINE, RT_OID_802_11_BSSID, cmdqelmt->bufferlength, cmdqelmt->buffer); RTUSBUp(pAdapter, &pAdapter->mlme_semaphore); } break; case OID_802_11_SSID: { if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! MLME busy (Line#%d)!!!\n", __LINE__); MlmeRestartStateMachine(pAdapter); MlmePostRestartStateMachine(pAdapter); } pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = FALSE; // Reset allowed scan retries pAdapter->PortCfg.IgnoredScanNumber = 0; MlmeEnqueue(pAdapter, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, cmdqelmt->bufferlength, pData); RTUSBUp(pAdapter, &pAdapter->mlme_semaphore); } break; case OID_802_11_DISASSOCIATE: { if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) { DBGPRINT_RAW(RT_DEBUG_TRACE, "!!! MLME busy (Line#%d)!!!\n", __LINE__); MlmeRestartStateMachine(pAdapter); MlmePostRestartStateMachine(pAdapter); } // Set to immediately send the media disconnect event pAdapter->Mlme.CntlAux.CurrReqIsFromNdis = TRUE; MlmeEnqueue(pAdapter, MLME_CNTL_STATE_MACHINE, OID_802_11_DISASSOCIATE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -