// SPDX-License-Identifier: GPL-2.0-or-later
/*
Copyright ( C ) 2010 Willow Garage < http : //www.willowgarage.com>
Copyright ( C ) 2009 - 2010 Ivo van Doorn < IvDoorn @ gmail . com >
Copyright ( C ) 2009 Mattias Nissler < mattias . nissler @ gmx . de >
Copyright ( C ) 2009 Felix Fietkau < nbd @ openwrt . org >
Copyright ( C ) 2009 Xose Vazquez Perez < xose . vazquez @ gmail . com >
Copyright ( C ) 2009 Axel Kollhofer < rain_maker @ root - forum . org >
< http : //rt2x00.serialmonkey.com>
*/
/*
Module : rt2800usb
Abstract : rt2800usb device specific routines .
Supported chipsets : RT2800U .
*/
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "rt2x00.h"
#include "rt2x00usb.h"
#include "rt2800lib.h"
#include "rt2800.h"
#include "rt2800usb.h"
/*
* Allow hardware encryption to be disabled .
*/
static bool modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool , 0444 );
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption." );
static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
{
return modparam_nohwcrypt;
}
/*
* Queue handlers .
*/
static void rt2800usb_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1 );
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break ;
case QID_BEACON:
reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1 );
rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1 );
rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1 );
rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break ;
default :
break ;
}
}
static void rt2800usb_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
reg = rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL);
rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0 );
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break ;
case QID_BEACON:
reg = rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG);
rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0 );
rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0 );
rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0 );
rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break ;
default :
break ;
}
}
#define TXSTATUS_READ_INTERVAL 1000000
static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
int urb_status, u32 tx_status)
{
bool valid;
if (urb_status) {
rt2x00_warn(rt2x00dev, "TX status read failed %d\n" ,
urb_status);
goto stop_reading;
}
valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
if (valid) {
if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status))
rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n" );
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
/* Reschedule urb to read TX status again instantly */
return true ;
}
/* Check if there is any entry that timedout waiting on TX status */
if (rt2800_txstatus_timeout(rt2x00dev))
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
if (rt2800_txstatus_pending(rt2x00dev)) {
/* Read register after 1 ms */
hrtimer_start(&rt2x00dev->txstatus_timer,
TXSTATUS_READ_INTERVAL,
HRTIMER_MODE_REL);
return false ;
}
stop_reading:
clear_bit(TX_STATUS_READING, &rt2x00dev->flags);
/*
* There is small race window above , between txstatus pending check and
* clear_bit someone could do rt2x00usb_interrupt_txdone , so recheck
* here again if status reading is needed .
*/
if (rt2800_txstatus_pending(rt2x00dev) &&
!test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
return true ;
else
return false ;
}
static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev)
{
if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
return ;
/* Read TX_STA_FIFO register after 2 ms */
hrtimer_start(&rt2x00dev->txstatus_timer,
2 * TXSTATUS_READ_INTERVAL,
HRTIMER_MODE_REL);
}
static void rt2800usb_tx_dma_done(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
rt2800usb_async_read_tx_status(rt2x00dev);
}
static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
{
struct rt2x00_dev *rt2x00dev =
container_of(timer, struct rt2x00_dev, txstatus_timer);
rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
rt2800usb_tx_sta_fifo_read_completed);
return HRTIMER_NORESTART;
}
/*
* Firmware functions
*/
static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
{
__le32 *reg;
u32 fw_mode;
int ret;
reg = kmalloc(sizeof (*reg), GFP_KERNEL);
if (reg == NULL)
return -ENOMEM;
/* cannot use rt2x00usb_register_read here as it uses different
* mode ( MULTI_READ vs . DEVICE_MODE ) and does not pass the
* magic value USB_MODE_AUTORUN ( 0 x11 ) to the device , thus the
* returned value would be invalid .
*/
ret = rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
USB_VENDOR_REQUEST_IN, 0 ,
USB_MODE_AUTORUN, reg, sizeof (*reg),
REGISTER_TIMEOUT_FIRMWARE);
fw_mode = le32_to_cpu(*reg);
kfree(reg);
if (ret < 0 )
return ret;
if ((fw_mode & 0 x00000003) == 2 )
return 1 ;
return 0 ;
}
static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
return FIRMWARE_RT2870;
}
static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len)
{
int status;
u32 offset;
u32 length;
int retval;
/*
* Check which section of the firmware we need .
*/
if (rt2x00_rt(rt2x00dev, RT2860) ||
rt2x00_rt(rt2x00dev, RT2872) ||
rt2x00_rt(rt2x00dev, RT3070)) {
offset = 0 ;
length = 4096 ;
} else {
offset = 4096 ;
length = 4096 ;
}
/*
* Write firmware to device .
*/
retval = rt2800usb_autorun_detect(rt2x00dev);
if (retval < 0 )
return retval;
if (retval) {
rt2x00_info(rt2x00dev,
"Firmware loading not required - NIC in AutoRun mode\n" );
__clear_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
} else {
rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
data + offset, length);
}
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0 );
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0 );
/*
* Send firmware request to device to load firmware ,
* we need to specify a long timeout time .
*/
status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
0 , USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0 ) {
rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n" );
return status;
}
msleep(10 );
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0 );
return 0 ;
}
/*
* Device state switch handlers .
*/
static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
/*
* Wait until BBP and RF are ready .
*/
if (rt2800_wait_csr_ready(rt2x00dev))
return -EBUSY;
reg = rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL);
rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0 x00002000);
reg = 0 ;
rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1 );
rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1 );
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0 ,
USB_MODE_RESET, REGISTER_TIMEOUT);
rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0 x00000000);
return 0 ;
}
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg = 0 ;
if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
return -EIO;
rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0 );
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0 );
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128 );
/*
* Total room for RX frames in kilobytes , PBF might still exceed
* this limit so reduce the number to prevent errors .
*/
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
((rt2x00dev->rx->limit * DATA_FRAME_SIZE)
/ 1024 ) - 3 );
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1 );
rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1 );
rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
return rt2800_enable_radio(rt2x00dev);
}
static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
rt2800_disable_radio(rt2x00dev);
}
static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
if (state == STATE_AWAKE)
rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0 xff, 0 , 2 );
else
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0 xff, 0 xff, 2 );
return 0 ;
}
static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
int retval = 0 ;
switch (state) {
case STATE_RADIO_ON:
/*
* Before the radio can be enabled , the device first has
* to be woken up . After that it needs a bit of time
* to be fully awake and then the radio can be enabled .
*/
rt2800usb_set_state(rt2x00dev, STATE_AWAKE);
msleep(1 );
retval = rt2800usb_enable_radio(rt2x00dev);
break ;
case STATE_RADIO_OFF:
/*
* After the radio has been disabled , the device should
* be put to sleep for powersaving .
*/
rt2800usb_disable_radio(rt2x00dev);
rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
break ;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_OFF:
/* No support, but no error either */
break ;
case STATE_DEEP_SLEEP:
case STATE_SLEEP:
case STATE_STANDBY:
case STATE_AWAKE:
retval = rt2800usb_set_state(rt2x00dev, state);
break ;
default :
retval = -ENOTSUPP;
break ;
}
if (unlikely(retval))
rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n" ,
state, retval);
return retval;
}
static unsigned int rt2800usb_get_dma_done(struct data_queue *queue)
{
struct queue_entry *entry;
entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
return entry->entry_idx;
}
/*
* TX descriptor initialization
*/
static __le32 *rt2800usb_get_txwi(struct queue_entry *entry)
{
if (entry->queue->qid == QID_BEACON)
return (__le32 *) (entry->skb->data);
else
return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
}
static void rt2800usb_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *txi = (__le32 *) entry->skb->data;
u32 word;
/*
* Initialize TXINFO descriptor
*/
word = rt2x00_desc_read(txi, 0 );
/*
* The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
* TXWI + 802 . 11 header + L2 pad + payload + pad ,
* so need to decrease size of TXINFO .
*/
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
roundup(entry->skb->len, 4 ) - TXINFO_DESC_SIZE);
rt2x00_set_field32(&word, TXINFO_W0_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2 );
rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0 );
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0 );
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST,
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_desc_write(txi, 0 , word);
/*
* Register descriptor details in skb frame descriptor .
*/
skbdesc->flags |= SKBDESC_DESC_IN_SKB;
skbdesc->desc = txi;
skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;
}
/*
* TX data initialization
*/
static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
{
/*
* pad ( 1 ~ 3 bytes ) is needed after each 802 . 11 payload .
* USB end pad ( 4 bytes ) is needed at each USB bulk out packet end .
* TX frame format is :
* | TXINFO | TXWI | 802 . 11 header | L2 pad | payload | pad | USB end pad |
* | < - - - - - - - - - - - - - tx_pkt_len - - - - - - - - - - - - - > |
*/
return roundup(entry->skb->len, 4 ) + 4 ;
}
/*
* TX control handlers
*/
static void rt2800usb_work_txdone(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, txdone_work);
while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
rt2800_txstatus_timeout(rt2x00dev)) {
rt2800_txdone(rt2x00dev, UINT_MAX);
rt2800_txdone_nostatus(rt2x00dev);
/*
* The hw may delay sending the packet after DMA complete
* if the medium is busy , thus the TX_STA_FIFO entry is
* also delayed - > use a timer to retrieve it .
*/
if (rt2800_txstatus_pending(rt2x00dev))
rt2800usb_async_read_tx_status(rt2x00dev);
}
}
/*
* RX control handlers
*/
static void rt2800usb_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxi = (__le32 *)entry->skb->data;
__le32 *rxd;
u32 word;
int rx_pkt_len;
/*
* Copy descriptor to the skbdesc - > desc buffer , making it safe from
* moving of frame data in rt2x00usb .
*/
memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
/*
* RX frame format is :
* | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
* | < - - - - - - - - - - - - rx_pkt_len - - - - - - - - - - - - - - > |
*/
word = rt2x00_desc_read(rxi, 0 );
rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
/*
* Remove the RXINFO structure from the sbk .
*/
skb_pull(entry->skb, RXINFO_DESC_SIZE);
/*
* Check for rx_pkt_len validity . Return if invalid , leaving
* rxdesc - > size zeroed out by the upper level .
*/
if (unlikely(rx_pkt_len == 0 ||
rx_pkt_len > entry->queue->data_size)) {
rt2x00_err(entry->queue->rt2x00dev,
"Bad frame size %d, forcing to 0\n" , rx_pkt_len);
return ;
}
rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
/*
* It is now safe to read the descriptor on all architectures .
*/
word = rt2x00_desc_read(rxd, 0 );
if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W0_CIPHER_ERROR);
if (rt2x00_get_field32(word, RXD_W0_DECRYPTED)) {
/*
* Hardware has stripped IV / EIV data from 802 . 11 frame during
* decryption . Unfortunately the descriptor doesn ' t contain
* any fields with the EIV / IV data either , so they can ' t
* be restored by rt2x00lib .
*/
rxdesc->flags |= RX_FLAG_IV_STRIPPED;
/*
* The hardware has already checked the Michael Mic and has
* stripped it from the frame . Signal this to mac80211 .
*/
rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) {
rxdesc->flags |= RX_FLAG_DECRYPTED;
} else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) {
/*
* In order to check the Michael Mic , the packet must have
* been decrypted . Mac80211 doesnt check the MMIC failure
* flag to initiate MMIC countermeasures if the decoded flag
* has not been set .
*/
rxdesc->flags |= RX_FLAG_DECRYPTED;
rxdesc->flags |= RX_FLAG_MMIC_ERROR;
}
}
if (rt2x00_get_field32(word, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;
if (rt2x00_get_field32(word, RXD_W0_L2PAD))
rxdesc->dev_flags |= RXDONE_L2PAD;
/*
* Remove RXD descriptor from end of buffer .
*/
skb_trim(entry->skb, rx_pkt_len);
/*
* Process the RXWI structure .
*/
rt2800_process_rxwi(entry, rxdesc);
}
/*
* Device probe functions .
*/
static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
{
int retval;
retval = rt2800usb_autorun_detect(rt2x00dev);
if (retval < 0 )
return retval;
if (retval)
return 1 ;
return rt2800_efuse_detect(rt2x00dev);
}
static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
{
int retval;
retval = rt2800usb_efuse_detect(rt2x00dev);
if (retval < 0 )
return retval;
if (retval)
retval = rt2800_read_eeprom_efuse(rt2x00dev);
else
retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
EEPROM_SIZE);
return retval;
}
static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
retval = rt2800_probe_hw(rt2x00dev);
if (retval)
return retval;
/*
* Set txstatus timer function .
*/
hrtimer_update_function(&rt2x00dev->txstatus_timer, rt2800usb_tx_sta_fifo_timeout);
/*
* Overwrite TX done handler
*/
INIT_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
return 0 ;
}
static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
.change_chanctx = ieee80211_emulate_change_chanctx,
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
.tx = rt2x00mac_tx,
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
.start = rt2x00mac_start,
.stop = rt2x00mac_stop,
.add_interface = rt2x00mac_add_interface,
.remove_interface = rt2x00mac_remove_interface,
.config = rt2x00mac_config,
.configure_filter = rt2x00mac_configure_filter,
.set_tim = rt2x00mac_set_tim,
.set_key = rt2x00mac_set_key,
.sw_scan_start = rt2x00mac_sw_scan_start,
.sw_scan_complete = rt2x00mac_sw_scan_complete,
.get_stats = rt2x00mac_get_stats,
.get_key_seq = rt2800_get_key_seq,
.set_rts_threshold = rt2800_set_rts_threshold,
.sta_add = rt2800_sta_add,
.sta_remove = rt2800_sta_remove,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
.get_ringparam = rt2x00mac_get_ringparam,
.tx_frames_pending = rt2x00mac_tx_frames_pending,
.reconfig_complete = rt2x00mac_reconfig_complete,
};
static const struct rt2800_ops rt2800usb_rt2800_ops = {
.register_read = rt2x00usb_register_read,
.register_read_lock = rt2x00usb_register_read_lock,
.register_write = rt2x00usb_register_write,
.register_write_lock = rt2x00usb_register_write_lock,
.register_multiread = rt2x00usb_register_multiread,
.register_multiwrite = rt2x00usb_register_multiwrite,
.regbusy_read = rt2x00usb_regbusy_read,
.read_eeprom = rt2800usb_read_eeprom,
.hwcrypt_disabled = rt2800usb_hwcrypt_disabled,
.drv_write_firmware = rt2800usb_write_firmware,
.drv_init_registers = rt2800usb_init_registers,
.drv_get_txwi = rt2800usb_get_txwi,
.drv_get_dma_done = rt2800usb_get_dma_done,
};
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.probe_hw = rt2800usb_probe_hw,
.get_firmware_name = rt2800usb_get_firmware_name,
.check_firmware = rt2800_check_firmware,
.load_firmware = rt2800_load_firmware,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
.clear_entry = rt2x00usb_clear_entry,
.set_device_state = rt2800usb_set_device_state,
.rfkill_poll = rt2800_rfkill_poll,
.link_stats = rt2800_link_stats,
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.gain_calibration = rt2800_gain_calibration,
.vco_calibration = rt2800_vco_calibration,
.watchdog = rt2800_watchdog,
.start_queue = rt2800usb_start_queue,
.kick_queue = rt2x00usb_kick_queue,
.stop_queue = rt2800usb_stop_queue,
.flush_queue = rt2x00usb_flush_queue,
.tx_dma_done = rt2800usb_tx_dma_done,
.write_tx_desc = rt2800usb_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
.clear_beacon = rt2800_clear_beacon,
.get_tx_data_len = rt2800usb_get_tx_data_len,
.fill_rxdone = rt2800usb_fill_rxdone,
.config_shared_key = rt2800_config_shared_key,
.config_pairwise_key = rt2800_config_pairwise_key,
.config_filter = rt2800_config_filter,
.config_intf = rt2800_config_intf,
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
.pre_reset_hw = rt2800_pre_reset_hw,
};
static void rt2800usb_queue_init(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
unsigned short txwi_size, rxwi_size;
rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size);
switch (queue->qid) {
case QID_RX:
queue->limit = 128 ;
queue->data_size = AGGREGATION_SIZE;
queue->desc_size = RXINFO_DESC_SIZE;
queue->winfo_size = rxwi_size;
queue->priv_size = sizeof (struct queue_entry_priv_usb);
break ;
case QID_AC_VO:
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
queue->limit = 16 ;
queue->data_size = AGGREGATION_SIZE;
queue->desc_size = TXINFO_DESC_SIZE;
queue->winfo_size = txwi_size;
queue->priv_size = sizeof (struct queue_entry_priv_usb);
break ;
case QID_BEACON:
queue->limit = 8 ;
queue->data_size = MGMT_FRAME_SIZE;
queue->desc_size = TXINFO_DESC_SIZE;
queue->winfo_size = txwi_size;
queue->priv_size = sizeof (struct queue_entry_priv_usb);
break ;
case QID_ATIM:
default :
BUG();
break ;
}
}
static const struct rt2x00_ops rt2800usb_ops = {
.name = KBUILD_MODNAME,
.drv_data_size = sizeof (struct rt2800_drv_data),
.max_ap_intf = 8 ,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
.tx_queues = NUM_TX_QUEUES,
.queue_init = rt2800usb_queue_init,
.lib = &rt2800usb_rt2x00_ops,
.drv = &rt2800usb_rt2800_ops,
.hw = &rt2800usb_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
.debugfs = &rt2800_rt2x00debug,
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
};
/*
* rt2800usb module information .
*/
static const struct usb_device_id rt2800usb_device_table[] = {
/* Abocom */
{ USB_DEVICE(0 x07b8, 0 x2870) },
{ USB_DEVICE(0 x07b8, 0 x2770) },
{ USB_DEVICE(0 x07b8, 0 x3070) },
{ USB_DEVICE(0 x07b8, 0 x3071) },
{ USB_DEVICE(0 x07b8, 0 x3072) },
{ USB_DEVICE(0 x1482, 0 x3c09) },
/* AirTies */
{ USB_DEVICE(0 x1eda, 0 x2012) },
{ USB_DEVICE(0 x1eda, 0 x2210) },
{ USB_DEVICE(0 x1eda, 0 x2310) },
/* Allwin */
{ USB_DEVICE(0 x8516, 0 x2070) },
{ USB_DEVICE(0 x8516, 0 x2770) },
{ USB_DEVICE(0 x8516, 0 x2870) },
{ USB_DEVICE(0 x8516, 0 x3070) },
{ USB_DEVICE(0 x8516, 0 x3071) },
{ USB_DEVICE(0 x8516, 0 x3072) },
/* Alpha Networks */
{ USB_DEVICE(0 x14b2, 0 x3c06) },
{ USB_DEVICE(0 x14b2, 0 x3c07) },
{ USB_DEVICE(0 x14b2, 0 x3c09) },
{ USB_DEVICE(0 x14b2, 0 x3c12) },
{ USB_DEVICE(0 x14b2, 0 x3c23) },
{ USB_DEVICE(0 x14b2, 0 x3c25) },
{ USB_DEVICE(0 x14b2, 0 x3c27) },
{ USB_DEVICE(0 x14b2, 0 x3c28) },
{ USB_DEVICE(0 x14b2, 0 x3c2c) },
/* Amit */
{ USB_DEVICE(0 x15c5, 0 x0008) },
/* Askey */
{ USB_DEVICE(0 x1690, 0 x0740) },
/* ASUS */
{ USB_DEVICE(0 x0b05, 0 x1731) },
{ USB_DEVICE(0 x0b05, 0 x1732) },
{ USB_DEVICE(0 x0b05, 0 x1742) },
{ USB_DEVICE(0 x0b05, 0 x1784) },
{ USB_DEVICE(0 x1761, 0 x0b05) },
/* AzureWave */
{ USB_DEVICE(0 x13d3, 0 x3247) },
{ USB_DEVICE(0 x13d3, 0 x3273) },
{ USB_DEVICE(0 x13d3, 0 x3305) },
{ USB_DEVICE(0 x13d3, 0 x3307) },
{ USB_DEVICE(0 x13d3, 0 x3321) },
/* Belkin */
{ USB_DEVICE(0 x050d, 0 x8053) },
{ USB_DEVICE(0 x050d, 0 x805c) },
{ USB_DEVICE(0 x050d, 0 x815c) },
{ USB_DEVICE(0 x050d, 0 x825a) },
{ USB_DEVICE(0 x050d, 0 x825b) },
{ USB_DEVICE(0 x050d, 0 x935a) },
{ USB_DEVICE(0 x050d, 0 x935b) },
/* Buffalo */
{ USB_DEVICE(0 x0411, 0 x00e8) },
{ USB_DEVICE(0 x0411, 0 x0158) },
{ USB_DEVICE(0 x0411, 0 x015d) },
{ USB_DEVICE(0 x0411, 0 x016f) },
{ USB_DEVICE(0 x0411, 0 x01a2) },
{ USB_DEVICE(0 x0411, 0 x01ee) },
{ USB_DEVICE(0 x0411, 0 x01a8) },
{ USB_DEVICE(0 x0411, 0 x01fd) },
/* Corega */
{ USB_DEVICE(0 x07aa, 0 x002f) },
{ USB_DEVICE(0 x07aa, 0 x003c) },
{ USB_DEVICE(0 x07aa, 0 x003f) },
{ USB_DEVICE(0 x18c5, 0 x0012) },
/* D-Link */
{ USB_DEVICE(0 x07d1, 0 x3c09) },
{ USB_DEVICE(0 x07d1, 0 x3c0a) },
{ USB_DEVICE(0 x07d1, 0 x3c0d) },
{ USB_DEVICE(0 x07d1, 0 x3c0e) },
{ USB_DEVICE(0 x07d1, 0 x3c0f) },
{ USB_DEVICE(0 x07d1, 0 x3c11) },
{ USB_DEVICE(0 x07d1, 0 x3c13) },
{ USB_DEVICE(0 x07d1, 0 x3c15) },
{ USB_DEVICE(0 x07d1, 0 x3c16) },
{ USB_DEVICE(0 x07d1, 0 x3c17) },
{ USB_DEVICE(0 x2001, 0 x3317) },
{ USB_DEVICE(0 x2001, 0 x3c1b) },
{ USB_DEVICE(0 x2001, 0 x3c25) },
/* Draytek */
{ USB_DEVICE(0 x07fa, 0 x7712) },
/* DVICO */
{ USB_DEVICE(0 x0fe9, 0 xb307) },
/* Edimax */
{ USB_DEVICE(0 x7392, 0 x4085) },
{ USB_DEVICE(0 x7392, 0 x7711) },
{ USB_DEVICE(0 x7392, 0 x7717) },
{ USB_DEVICE(0 x7392, 0 x7718) },
{ USB_DEVICE(0 x7392, 0 x7722) },
/* Encore */
{ USB_DEVICE(0 x203d, 0 x1480) },
{ USB_DEVICE(0 x203d, 0 x14a9) },
/* EnGenius */
{ USB_DEVICE(0 x1740, 0 x9701) },
{ USB_DEVICE(0 x1740, 0 x9702) },
{ USB_DEVICE(0 x1740, 0 x9703) },
{ USB_DEVICE(0 x1740, 0 x9705) },
{ USB_DEVICE(0 x1740, 0 x9706) },
{ USB_DEVICE(0 x1740, 0 x9707) },
{ USB_DEVICE(0 x1740, 0 x9708) },
{ USB_DEVICE(0 x1740, 0 x9709) },
/* Gemtek */
{ USB_DEVICE(0 x15a9, 0 x0012) },
/* Gigabyte */
{ USB_DEVICE(0 x1044, 0 x800b) },
{ USB_DEVICE(0 x1044, 0 x800d) },
/* Hawking */
{ USB_DEVICE(0 x0e66, 0 x0001) },
{ USB_DEVICE(0 x0e66, 0 x0003) },
{ USB_DEVICE(0 x0e66, 0 x0009) },
{ USB_DEVICE(0 x0e66, 0 x000b) },
{ USB_DEVICE(0 x0e66, 0 x0013) },
{ USB_DEVICE(0 x0e66, 0 x0017) },
{ USB_DEVICE(0 x0e66, 0 x0018) },
/* I-O DATA */
{ USB_DEVICE(0 x04bb, 0 x0945) },
{ USB_DEVICE(0 x04bb, 0 x0947) },
{ USB_DEVICE(0 x04bb, 0 x0948) },
/* Linksys */
{ USB_DEVICE(0 x13b1, 0 x0031) },
{ USB_DEVICE(0 x1737, 0 x0070) },
{ USB_DEVICE(0 x1737, 0 x0071) },
{ USB_DEVICE(0 x1737, 0 x0077) },
{ USB_DEVICE(0 x1737, 0 x0078) },
/* Logitec */
{ USB_DEVICE(0 x0789, 0 x0162) },
{ USB_DEVICE(0 x0789, 0 x0163) },
{ USB_DEVICE(0 x0789, 0 x0164) },
{ USB_DEVICE(0 x0789, 0 x0166) },
/* Motorola */
{ USB_DEVICE(0 x100d, 0 x9031) },
/* MSI */
{ USB_DEVICE(0 x0db0, 0 x3820) },
{ USB_DEVICE(0 x0db0, 0 x3821) },
{ USB_DEVICE(0 x0db0, 0 x3822) },
{ USB_DEVICE(0 x0db0, 0 x3870) },
{ USB_DEVICE(0 x0db0, 0 x3871) },
{ USB_DEVICE(0 x0db0, 0 x6899) },
{ USB_DEVICE(0 x0db0, 0 x821a) },
{ USB_DEVICE(0 x0db0, 0 x822a) },
{ USB_DEVICE(0 x0db0, 0 x822b) },
{ USB_DEVICE(0 x0db0, 0 x822c) },
{ USB_DEVICE(0 x0db0, 0 x870a) },
{ USB_DEVICE(0 x0db0, 0 x871a) },
{ USB_DEVICE(0 x0db0, 0 x871b) },
{ USB_DEVICE(0 x0db0, 0 x871c) },
{ USB_DEVICE(0 x0db0, 0 x899a) },
/* Ovislink */
{ USB_DEVICE(0 x1b75, 0 x3070) },
{ USB_DEVICE(0 x1b75, 0 x3071) },
{ USB_DEVICE(0 x1b75, 0 x3072) },
{ USB_DEVICE(0 x1b75, 0 xa200) },
/* Para */
{ USB_DEVICE(0 x20b8, 0 x8888) },
/* Pegatron */
{ USB_DEVICE(0 x1d4d, 0 x0002) },
{ USB_DEVICE(0 x1d4d, 0 x000c) },
{ USB_DEVICE(0 x1d4d, 0 x000e) },
{ USB_DEVICE(0 x1d4d, 0 x0011) },
/* Philips */
{ USB_DEVICE(0 x0471, 0 x200f) },
/* Planex */
{ USB_DEVICE(0 x2019, 0 x5201) },
{ USB_DEVICE(0 x2019, 0 xab25) },
{ USB_DEVICE(0 x2019, 0 xed06) },
/* Quanta */
{ USB_DEVICE(0 x1a32, 0 x0304) },
/* Ralink */
{ USB_DEVICE(0 x148f, 0 x2070) },
{ USB_DEVICE(0 x148f, 0 x2770) },
{ USB_DEVICE(0 x148f, 0 x2870) },
{ USB_DEVICE(0 x148f, 0 x3070) },
{ USB_DEVICE(0 x148f, 0 x3071) },
{ USB_DEVICE(0 x148f, 0 x3072) },
/* Samsung */
{ USB_DEVICE(0 x04e8, 0 x2018) },
/* Siemens */
{ USB_DEVICE(0 x129b, 0 x1828) },
/* Sitecom */
{ USB_DEVICE(0 x0df6, 0 x0017) },
{ USB_DEVICE(0 x0df6, 0 x002b) },
{ USB_DEVICE(0 x0df6, 0 x002c) },
{ USB_DEVICE(0 x0df6, 0 x002d) },
{ USB_DEVICE(0 x0df6, 0 x0039) },
{ USB_DEVICE(0 x0df6, 0 x003b) },
{ USB_DEVICE(0 x0df6, 0 x003d) },
{ USB_DEVICE(0 x0df6, 0 x003e) },
{ USB_DEVICE(0 x0df6, 0 x003f) },
{ USB_DEVICE(0 x0df6, 0 x0040) },
{ USB_DEVICE(0 x0df6, 0 x0042) },
{ USB_DEVICE(0 x0df6, 0 x0047) },
{ USB_DEVICE(0 x0df6, 0 x0048) },
{ USB_DEVICE(0 x0df6, 0 x0051) },
{ USB_DEVICE(0 x0df6, 0 x005f) },
{ USB_DEVICE(0 x0df6, 0 x0060) },
/* SMC */
{ USB_DEVICE(0 x083a, 0 x6618) },
{ USB_DEVICE(0 x083a, 0 x7511) },
{ USB_DEVICE(0 x083a, 0 x7512) },
{ USB_DEVICE(0 x083a, 0 x7522) },
{ USB_DEVICE(0 x083a, 0 x8522) },
{ USB_DEVICE(0 x083a, 0 xa618) },
{ USB_DEVICE(0 x083a, 0 xa701) },
{ USB_DEVICE(0 x083a, 0 xa702) },
{ USB_DEVICE(0 x083a, 0 xa703) },
{ USB_DEVICE(0 x083a, 0 xb522) },
/* Sparklan */
{ USB_DEVICE(0 x15a9, 0 x0006) },
/* Sweex */
{ USB_DEVICE(0 x177f, 0 x0153) },
{ USB_DEVICE(0 x177f, 0 x0164) },
{ USB_DEVICE(0 x177f, 0 x0302) },
{ USB_DEVICE(0 x177f, 0 x0313) },
{ USB_DEVICE(0 x177f, 0 x0323) },
{ USB_DEVICE(0 x177f, 0 x0324) },
{ USB_DEVICE(0 x177f, 0 x1163) },
/* U-Media */
{ USB_DEVICE(0 x157e, 0 x300e) },
{ USB_DEVICE(0 x157e, 0 x3013) },
/* ZCOM */
{ USB_DEVICE(0 x0cde, 0 x0022) },
{ USB_DEVICE(0 x0cde, 0 x0025) },
/* Zinwell */
{ USB_DEVICE(0 x5a57, 0 x0280) },
{ USB_DEVICE(0 x5a57, 0 x0282) },
{ USB_DEVICE(0 x5a57, 0 x0283) },
{ USB_DEVICE(0 x5a57, 0 x5257) },
/* Zyxel */
{ USB_DEVICE(0 x0586, 0 x3416) },
{ USB_DEVICE(0 x0586, 0 x3418) },
{ USB_DEVICE(0 x0586, 0 x341a) },
{ USB_DEVICE(0 x0586, 0 x341e) },
{ USB_DEVICE(0 x0586, 0 x343e) },
#ifdef CONFIG_RT2800USB_RT33XX
/* Belkin */
{ USB_DEVICE(0 x050d, 0 x945b) },
/* D-Link */
{ USB_DEVICE(0 x2001, 0 x3c17) },
/* Panasonic */
{ USB_DEVICE(0 x083a, 0 xb511) },
/* Accton/Arcadyan/Epson */
{ USB_DEVICE(0 x083a, 0 xb512) },
/* Philips */
{ USB_DEVICE(0 x0471, 0 x20dd) },
/* Ralink */
{ USB_DEVICE(0 x148f, 0 x3370) },
{ USB_DEVICE(0 x148f, 0 x8070) },
/* Sitecom */
{ USB_DEVICE(0 x0df6, 0 x0050) },
/* Sweex */
{ USB_DEVICE(0 x177f, 0 x0163) },
{ USB_DEVICE(0 x177f, 0 x0165) },
#endif
#ifdef CONFIG_RT2800USB_RT35XX
/* Allwin */
{ USB_DEVICE(0 x8516, 0 x3572) },
/* Askey */
{ USB_DEVICE(0 x1690, 0 x0744) },
{ USB_DEVICE(0 x1690, 0 x0761) },
{ USB_DEVICE(0 x1690, 0 x0764) },
/* ASUS */
{ USB_DEVICE(0 x0b05, 0 x179d) },
/* Cisco */
{ USB_DEVICE(0 x167b, 0 x4001) },
/* EnGenius */
{ USB_DEVICE(0 x1740, 0 x9801) },
/* I-O DATA */
{ USB_DEVICE(0 x04bb, 0 x0944) },
/* Linksys */
{ USB_DEVICE(0 x13b1, 0 x002f) },
{ USB_DEVICE(0 x1737, 0 x0079) },
/* Logitec */
{ USB_DEVICE(0 x0789, 0 x0170) },
/* Ralink */
{ USB_DEVICE(0 x148f, 0 x3572) },
/* Sitecom */
{ USB_DEVICE(0 x0df6, 0 x0041) },
{ USB_DEVICE(0 x0df6, 0 x0062) },
{ USB_DEVICE(0 x0df6, 0 x0065) },
{ USB_DEVICE(0 x0df6, 0 x0066) },
{ USB_DEVICE(0 x0df6, 0 x0068) },
/* Toshiba */
{ USB_DEVICE(0 x0930, 0 x0a07) },
/* Zinwell */
{ USB_DEVICE(0 x5a57, 0 x0284) },
#endif
#ifdef CONFIG_RT2800USB_RT3573
/* AirLive */
{ USB_DEVICE(0 x1b75, 0 x7733) },
/* ASUS */
{ USB_DEVICE(0 x0b05, 0 x17bc) },
{ USB_DEVICE(0 x0b05, 0 x17ad) },
/* Belkin */
{ USB_DEVICE(0 x050d, 0 x1103) },
/* Cameo */
{ USB_DEVICE(0 x148f, 0 xf301) },
/* D-Link */
{ USB_DEVICE(0 x2001, 0 x3c1f) },
/* Edimax */
{ USB_DEVICE(0 x7392, 0 x7733) },
/* Hawking */
{ USB_DEVICE(0 x0e66, 0 x0020) },
{ USB_DEVICE(0 x0e66, 0 x0021) },
/* I-O DATA */
{ USB_DEVICE(0 x04bb, 0 x094e) },
/* Linksys */
{ USB_DEVICE(0 x13b1, 0 x003b) },
/* Logitec */
{ USB_DEVICE(0 x0789, 0 x016b) },
/* NETGEAR */
{ USB_DEVICE(0 x0846, 0 x9012) },
{ USB_DEVICE(0 x0846, 0 x9013) },
{ USB_DEVICE(0 x0846, 0 x9019) },
/* Planex */
{ USB_DEVICE(0 x2019, 0 xed14) },
{ USB_DEVICE(0 x2019, 0 xed19) },
/* Ralink */
{ USB_DEVICE(0 x148f, 0 x3573) },
/* Sitecom */
{ USB_DEVICE(0 x0df6, 0 x0067) },
{ USB_DEVICE(0 x0df6, 0 x006a) },
{ USB_DEVICE(0 x0df6, 0 x006e) },
/* ZyXEL */
{ USB_DEVICE(0 x0586, 0 x3421) },
#endif
#ifdef CONFIG_RT2800USB_RT53XX
/* Arcadyan */
{ USB_DEVICE(0 x043e, 0 x7a12) },
/* ASUS */
{ USB_DEVICE(0 x0b05, 0 x17e8) },
/* Azurewave */
{ USB_DEVICE(0 x13d3, 0 x3329) },
{ USB_DEVICE(0 x13d3, 0 x3365) },
/* D-Link */
{ USB_DEVICE(0 x2001, 0 x3c15) },
{ USB_DEVICE(0 x2001, 0 x3c19) },
{ USB_DEVICE(0 x2001, 0 x3c1c) },
{ USB_DEVICE(0 x2001, 0 x3c1d) },
{ USB_DEVICE(0 x2001, 0 x3c1e) },
{ USB_DEVICE(0 x2001, 0 x3c20) },
{ USB_DEVICE(0 x2001, 0 x3c22) },
{ USB_DEVICE(0 x2001, 0 x3c23) },
/* LG innotek */
{ USB_DEVICE(0 x043e, 0 x7a22) },
{ USB_DEVICE(0 x043e, 0 x7a42) },
/* Panasonic */
{ USB_DEVICE(0 x04da, 0 x1801) },
{ USB_DEVICE(0 x04da, 0 x1800) },
{ USB_DEVICE(0 x04da, 0 x23f6) },
/* Philips */
{ USB_DEVICE(0 x0471, 0 x2104) },
{ USB_DEVICE(0 x0471, 0 x2126) },
{ USB_DEVICE(0 x0471, 0 x2180) },
{ USB_DEVICE(0 x0471, 0 x2181) },
{ USB_DEVICE(0 x0471, 0 x2182) },
/* Ralink */
{ USB_DEVICE(0 x148f, 0 x5370) },
{ USB_DEVICE(0 x148f, 0 x5372) },
#endif
#ifdef CONFIG_RT2800USB_RT55XX
/* Arcadyan */
{ USB_DEVICE(0 x043e, 0 x7a32) },
/* AVM GmbH */
{ USB_DEVICE(0 x057c, 0 x8501) },
/* Buffalo */
{ USB_DEVICE(0 x0411, 0 x0241) },
{ USB_DEVICE(0 x0411, 0 x0253) },
/* D-Link */
{ USB_DEVICE(0 x2001, 0 x3c1a) },
{ USB_DEVICE(0 x2001, 0 x3c21) },
/* Proware */
{ USB_DEVICE(0 x043e, 0 x7a13) },
/* Ralink */
{ USB_DEVICE(0 x148f, 0 x5572) },
/* TRENDnet */
{ USB_DEVICE(0 x20f4, 0 x724a) },
#endif
#ifdef CONFIG_RT2800USB_UNKNOWN
/*
* Unclear what kind of devices these are ( they aren ' t supported by the
* vendor linux driver ) .
*/
/* Abocom */
{ USB_DEVICE(0 x07b8, 0 x3073) },
{ USB_DEVICE(0 x07b8, 0 x3074) },
/* Alpha Networks */
{ USB_DEVICE(0 x14b2, 0 x3c08) },
{ USB_DEVICE(0 x14b2, 0 x3c11) },
/* Amigo */
{ USB_DEVICE(0 x0e0b, 0 x9031) },
{ USB_DEVICE(0 x0e0b, 0 x9041) },
/* ASUS */
{ USB_DEVICE(0 x0b05, 0 x166a) },
{ USB_DEVICE(0 x0b05, 0 x1760) },
{ USB_DEVICE(0 x0b05, 0 x1761) },
{ USB_DEVICE(0 x0b05, 0 x1790) },
{ USB_DEVICE(0 x0b05, 0 x17a7) },
/* AzureWave */
{ USB_DEVICE(0 x13d3, 0 x3262) },
{ USB_DEVICE(0 x13d3, 0 x3284) },
{ USB_DEVICE(0 x13d3, 0 x3322) },
{ USB_DEVICE(0 x13d3, 0 x3340) },
{ USB_DEVICE(0 x13d3, 0 x3399) },
{ USB_DEVICE(0 x13d3, 0 x3400) },
{ USB_DEVICE(0 x13d3, 0 x3401) },
/* Belkin */
{ USB_DEVICE(0 x050d, 0 x1003) },
/* Buffalo */
{ USB_DEVICE(0 x0411, 0 x012e) },
{ USB_DEVICE(0 x0411, 0 x0148) },
{ USB_DEVICE(0 x0411, 0 x0150) },
/* Corega */
{ USB_DEVICE(0 x07aa, 0 x0041) },
{ USB_DEVICE(0 x07aa, 0 x0042) },
{ USB_DEVICE(0 x18c5, 0 x0008) },
/* D-Link */
{ USB_DEVICE(0 x07d1, 0 x3c0b) },
/* Encore */
{ USB_DEVICE(0 x203d, 0 x14a1) },
/* EnGenius */
{ USB_DEVICE(0 x1740, 0 x0600) },
{ USB_DEVICE(0 x1740, 0 x0602) },
/* Gemtek */
{ USB_DEVICE(0 x15a9, 0 x0010) },
/* Gigabyte */
{ USB_DEVICE(0 x1044, 0 x800c) },
/* Hercules */
{ USB_DEVICE(0 x06f8, 0 xe036) },
/* Huawei */
{ USB_DEVICE(0 x148f, 0 xf101) },
/* I-O DATA */
{ USB_DEVICE(0 x04bb, 0 x094b) },
/* LevelOne */
{ USB_DEVICE(0 x1740, 0 x0605) },
{ USB_DEVICE(0 x1740, 0 x0615) },
/* Logitec */
{ USB_DEVICE(0 x0789, 0 x0168) },
{ USB_DEVICE(0 x0789, 0 x0169) },
/* Motorola */
{ USB_DEVICE(0 x100d, 0 x9032) },
/* Pegatron */
{ USB_DEVICE(0 x05a6, 0 x0101) },
{ USB_DEVICE(0 x1d4d, 0 x0010) },
/* Planex */
{ USB_DEVICE(0 x2019, 0 xab24) },
{ USB_DEVICE(0 x2019, 0 xab29) },
/* Qcom */
{ USB_DEVICE(0 x18e8, 0 x6259) },
/* RadioShack */
{ USB_DEVICE(0 x08b9, 0 x1197) },
/* Sitecom */
{ USB_DEVICE(0 x0df6, 0 x003c) },
{ USB_DEVICE(0 x0df6, 0 x004a) },
{ USB_DEVICE(0 x0df6, 0 x004d) },
{ USB_DEVICE(0 x0df6, 0 x0053) },
{ USB_DEVICE(0 x0df6, 0 x0069) },
{ USB_DEVICE(0 x0df6, 0 x006f) },
{ USB_DEVICE(0 x0df6, 0 x0078) },
/* SMC */
{ USB_DEVICE(0 x083a, 0 xa512) },
{ USB_DEVICE(0 x083a, 0 xc522) },
{ USB_DEVICE(0 x083a, 0 xd522) },
{ USB_DEVICE(0 x083a, 0 xf511) },
/* Sweex */
{ USB_DEVICE(0 x177f, 0 x0254) },
/* TP-LINK */
{ USB_DEVICE(0 xf201, 0 x5370) },
#endif
{ 0 , }
};
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver." );
MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2870);
MODULE_LICENSE("GPL" );
static int rt2800usb_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
{
return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
}
static struct usb_driver rt2800usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2800usb_device_table,
.probe = rt2800usb_probe,
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
.reset_resume = rt2x00usb_resume,
.disable_hub_initiated_lpm = 1 ,
};
module_usb_driver(rt2800usb_driver);
Messung V0.5 in Prozent C=88 H=99 G=93
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.25Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-02)
¤
*Eine klare Vorstellung vom Zielzustand