📄 rtusb_io.c
字号:
/*
========================================================================
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
NTSTATUS RTUSBWakeUp(
IN PRTMP_ADAPTER pAd)
{
NTSTATUS Status;
Status = RTUSB_VendorRequest(
pAd,
0,
DEVICE_VENDOR_REQUEST_OUT,
0x01,
0x09,
0,
NULL,
0);
return Status;
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
VOID RTUSBInitializeCmdQ(
IN PCmdQ cmdq)
{
cmdq->head = NULL;
cmdq->tail = NULL;
cmdq->size = 0;
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
NDIS_STATUS RTUSBEnqueueCmdFromNdis(
IN PRTMP_ADAPTER pAd,
IN NDIS_OID Oid,
IN BOOLEAN SetInformation,
IN PVOID pInformationBuffer,
IN ULONG InformationBufferLength)
{
PCmdQElmt cmdqelmt = NULL;
unsigned long IrqFlags;
if (pAd->RTUSBCmdThr_pid < 0)
return (NDIS_STATUS_RESOURCES);
cmdqelmt = (PCmdQElmt) kmalloc(sizeof(CmdQElmt), MEM_ALLOC_FLAG);
if (!cmdqelmt)
{
DBGPRINT(RT_DEBUG_ERROR,"Not enough memory\n");
kfree((PCmdQElmt)cmdqelmt);
return NDIS_STATUS_RESOURCES;
}
if ((Oid == RT_OID_MULTI_READ_MAC) ||
(Oid == RT_OID_VENDOR_READ_BBP) ||
#ifdef DBG
(Oid == RT_OID_802_11_QUERY_HARDWARE_REGISTER) ||
#endif
(Oid == RT_OID_USB_VENDOR_EEPROM_READ))
{
cmdqelmt->buffer = pInformationBuffer;
}
else
{
cmdqelmt->buffer = NULL;
if (pInformationBuffer != NULL)
{
cmdqelmt->buffer = kmalloc(InformationBufferLength, MEM_ALLOC_FLAG);
if ((!cmdqelmt->buffer) )
{
kfree((PVOID)cmdqelmt->buffer);
kfree((PCmdQElmt)cmdqelmt);
return (NDIS_STATUS_RESOURCES);
}
else
{
NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength);
cmdqelmt->bufferlength = InformationBufferLength;
}
}
else
cmdqelmt->bufferlength = 0;
}
cmdqelmt->command = Oid;
cmdqelmt->CmdFromNdis = TRUE;
if (SetInformation == TRUE)
cmdqelmt->SetOperation = TRUE;
else
cmdqelmt->SetOperation = FALSE;
NdisAcquireSpinLock(&pAd->CmdQLock, IrqFlags);
EnqueueCmd((&pAd->CmdQ), cmdqelmt);
NdisReleaseSpinLock(&pAd->CmdQLock, IrqFlags);
RTUSBCMDUp(pAd);
if ((Oid == OID_802_11_BSSID_LIST_SCAN) ||
(Oid == RT_OID_802_11_BSSID) ||
(Oid == OID_802_11_SSID) ||
(Oid == OID_802_11_DISASSOCIATE))
{
return(NDIS_STATUS_SUCCESS);
}
return(NDIS_STATUS_SUCCESS);
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
VOID RTUSBEnqueueInternalCmd(
IN PRTMP_ADAPTER pAd,
IN NDIS_OID Oid)
{
PCmdQElmt cmdqelmt = NULL;
unsigned long IrqFlags;
if (pAd->RTUSBCmdThr_pid < 0)
return;
switch (Oid)
{
case RT_OID_CHECK_GPIO:
cmdqelmt = &(pAd->CmdQElements[CMD_CHECK_GPIO]);
break;
case RT_OID_PERIODIC_EXECUT:
cmdqelmt = &(pAd->CmdQElements[CMD_PERIODIC_EXECUT]);
break;
//For Alpha only
case RT_OID_ASICLED_EXECUT:
cmdqelmt = &(pAd->CmdQElements[CMD_ASICLED_EXECUT]);
break;
case RT_OID_UPDATE_TX_RATE:
cmdqelmt = &(pAd->CmdQElements[CMD_UPDATE_TX_RATE]);
break;
case RT_OID_SET_PSM_BIT_SAVE:
cmdqelmt = &(pAd->CmdQElements[CMD_SET_PSM_SAVE]);
break;
case RT_OID_LINK_DOWN:
cmdqelmt = &(pAd->CmdQElements[CMD_LINK_DOWN]);
break;
case RT_OID_USB_RESET_BULK_IN:
cmdqelmt = &(pAd->CmdQElements[CMD_RESET_BULKIN]);
break;
case RT_OID_USB_RESET_BULK_OUT:
cmdqelmt = &(pAd->CmdQElements[CMD_RESET_BULKOUT]);
break;
case RT_OID_RESET_FROM_ERROR:
cmdqelmt = &(pAd->CmdQElements[CMD_RESET_FROM_ERROR]);
break;
case RT_OID_RESET_FROM_NDIS:
cmdqelmt = &(pAd->CmdQElements[CMD_RESET_FROM_NDIS]);
break;
case RT_PERFORM_SOFT_DIVERSITY:
cmdqelmt = &(pAd->CmdQElements[CMD_SOFT_DIVERSITY]);
break;
case RT_OID_FORCE_WAKE_UP:
cmdqelmt = &(pAd->CmdQElements[CMD_FORCE_WAKEUP]);
break;
case RT_OID_SET_PSM_BIT_ACTIVE:
cmdqelmt = &(pAd->CmdQElements[CMD_SET_PSM_ACTIVE]);
break;
default:
break;
}
if ((cmdqelmt != NULL) && (cmdqelmt->InUse == FALSE) && (pAd->RTUSBCmdThr_pid > 0))
{
cmdqelmt->InUse = TRUE;
cmdqelmt->command = Oid;
NdisAcquireSpinLock(&pAd->CmdQLock, IrqFlags);
EnqueueCmd((&pAd->CmdQ), cmdqelmt);
NdisReleaseSpinLock(&pAd->CmdQLock, IrqFlags);
RTUSBCMDUp(pAd);
}
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
VOID RTUSBDequeueCmd(
IN PCmdQ cmdq,
OUT PCmdQElmt *pcmdqelmt)
{
*pcmdqelmt = cmdq->head;
if (*pcmdqelmt != NULL)
{
cmdq->head = cmdq->head->next;
cmdq->size--;
if (cmdq->size == 0)
cmdq->tail = NULL;
}
}
/*
========================================================================
usb_control_msg - Builds a control urb, sends it off and waits for completion
@dev: pointer to the usb device to send the message to
@pipe: endpoint "pipe" to send the message to
@request: USB message request value
@requesttype: USB message request type value
@value: USB message value
@index: USB message index value
@data: pointer to the data to send
@size: length in bytes of the data to send
@timeout: time in jiffies to wait for the message to complete before
timing out (if 0 the wait is forever)
Context: !in_interrupt ()
This function sends a simple control message to a specified endpoint
and waits for the message to complete, or timeout.
If successful, it returns the number of bytes transferred, otherwise a negative error number.
Don't use this function from within an interrupt context, like a
bottom half handler. If you need an asynchronous message, or need to send
a message from within interrupt context, use usb_submit_urb()
If a thread in your driver uses this call, make sure your disconnect()
method can wait for it to complete. Since you don't have a handle on
the URB used, you can't cancel the request.
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
INT RTUSB_VendorRequest(
IN PRTMP_ADAPTER pAd,
IN ULONG TransferFlags,
IN UCHAR RequestType,
IN UCHAR Request,
IN USHORT Value,
IN USHORT Index,
IN PVOID TransferBuffer,
IN ULONG TransferBufferLength)
{
int ret;
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
{
DBGPRINT(RT_DEBUG_ERROR,"device disconnected\n");
return -1;
}
else if (in_interrupt())
{
DBGPRINT(RT_DEBUG_ERROR,"in_interrupt, return RTUSB_VendorRequest\n");
return -1;
}
else
{
if( RequestType == DEVICE_VENDOR_REQUEST_OUT)
ret=usb_control_msg(pAd->pUsb_Dev, usb_sndctrlpipe( pAd->pUsb_Dev, 0 ), Request, RequestType, Value,Index, TransferBuffer, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
else if(RequestType == DEVICE_VENDOR_REQUEST_IN)
ret=usb_control_msg(pAd->pUsb_Dev, usb_rcvctrlpipe( pAd->pUsb_Dev, 0 ), Request, RequestType, Value,Index, TransferBuffer, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
else
{
DBGPRINT(RT_DEBUG_ERROR,"vendor request direction is failed\n");
ret = -1;
}
if (ret < 0)
DBGPRINT(RT_DEBUG_ERROR,"USBVendorRequest failed ret=%d \n",ret);
#if 0
// retry
if (ret < 0) {
int temp_i=0;
DBGPRINT(RT_DEBUG_ERROR,"USBVendorRequest failed ret=%d, \n",ret);
ret = 0;
do
{
if( RequestType == DEVICE_VENDOR_REQUEST_OUT)
ret=usb_control_msg(pAd->pUsb_Dev, usb_sndctrlpipe( pAd->pUsb_Dev, 0 ), Request, RequestType, Value,Index, TransferBuffer, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
else if(RequestType == DEVICE_VENDOR_REQUEST_IN)
ret=usb_control_msg(pAd->pUsb_Dev, usb_rcvctrlpipe( pAd->pUsb_Dev, 0 ), Request, RequestType, Value,Index, TransferBuffer, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
temp_i++;
} while( (ret < 0) && (temp_i <= 1) );
if( ret >= 0)
return ret;
}
#endif
}
return ret;
}
/*
========================================================================
Routine Description:
Creates an IRP to submite an IOCTL_INTERNAL_USB_RESET_PORT
synchronously. Callers of this function must be running at
PASSIVE LEVEL.
Arguments:
Return Value:
Note:
========================================================================
*/
NTSTATUS RTUSB_ResetDevice(
IN PRTMP_ADAPTER pAd)
{
NTSTATUS Status = TRUE;
DBGPRINT_RAW(RT_DEBUG_TRACE, "--->USB_ResetDevice\n");
//RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);
return Status;
}
VOID CMDHandler(
IN PRTMP_ADAPTER pAd)
{
PCmdQElmt cmdqelmt;
PUCHAR pData;
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
unsigned long IrqFlags;
ULONG Now;
while (pAd->CmdQ.size > 0)
{
NdisStatus = NDIS_STATUS_SUCCESS;
NdisAcquireSpinLock(&pAd->CmdQLock, IrqFlags);
RTUSBDequeueCmd(&pAd->CmdQ, &cmdqelmt);
NdisReleaseSpinLock(&pAd->CmdQLock, IrqFlags);
if (cmdqelmt == NULL)
break;
pData = cmdqelmt->buffer;
//DBGPRINT_RAW(RT_DEBUG_INFO, "Cmd = %x\n", cmdqelmt->command);
switch (cmdqelmt->command)
{
case RT_OID_CHECK_GPIO:
{
ULONG data;
// Read GPIO pin7 as Hardware controlled radio state
RTUSBReadMACRegister(pAd, MAC_CSR13, &data);
if (data & 0x80)
{
pAd->PortCfg.bHwRadio = TRUE;
}
else
{
pAd->PortCfg.bHwRadio = FALSE;
}
if (pAd->PortCfg.bRadio != (pAd->PortCfg.bHwRadio && pAd->PortCfg.bSwRadio))
{
pAd->PortCfg.bRadio = (pAd->PortCfg.bHwRadio && pAd->PortCfg.bSwRadio);
if (pAd->PortCfg.bRadio == TRUE)
{
MlmeRadioOn(pAd);
// Update extra information
pAd->ExtraInfo = EXTRA_INFO_CLEAR;
}
else
{
MlmeRadioOff(pAd);
// Update extra information
pAd->ExtraInfo = HW_RADIO_OFF;
}
}
}
break;
case RT_OID_PERIODIC_EXECUT:
STAMlmePeriodicExec(pAd);
break;
case OID_802_11_BSSID_LIST_SCAN:
{
if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
{
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_CMD_RESET_MLME,
0,
NULL);
}
Now = jiffies;
// Reset Missed scan number
pAd->PortCfg.ScanCnt = 0;
pAd->PortCfg.LastScanTime = Now;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_BSSID_LIST_SCAN,
0,
NULL);
RTUSBMlmeUp(pAd);
}
break;
case RT_OID_802_11_BSSID:
{
if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
{
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_CMD_RESET_MLME,
0,
NULL);
}
// Reset allowed scan retries
pAd->PortCfg.ScanCnt = 0;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_BSSID,
cmdqelmt->bufferlength,
cmdqelmt->buffer);
RTUSBMlmeUp(pAd);
}
break;
case OID_802_11_SSID:
{
if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
{
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_CMD_RESET_MLME,
0,
NULL);
}
// Reset allowed scan retries
pAd->PortCfg.ScanCnt = 0;
pAd->bConfigChanged = TRUE;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_SSID,
cmdqelmt->bufferlength,
pData);
RTUSBMlmeUp(pAd);
}
break;
case OID_802_11_DISASSOCIATE:
{
if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
{
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_CMD_RESET_MLME,
0,
NULL);
}
// Set to immediately send the media disconnect event
pAd->MlmeAux.CurrReqIsFromNdis = TRUE;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_DISASSOCIATE,
0,
NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -