========================================================================
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:
========================================================================
*/
NTSTATUS RTUSB_VendorRequest(
IN PRTMP_ADAPTER pAd,
IN UINT32 TransferFlags,
IN UCHAR RequestType,
IN UCHAR Request,
IN USHORT Value,
IN USHORT Index,
IN PVOID TransferBuffer,
IN UINT32 TransferBufferLength)
{
int ret = 0;
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
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, RTUSB_VendorRequest Request%02x Value%04x Offset%04x\n",Request,Value,Index));
return -1;
}
else
{
#define MAX_RETRY_COUNT 10
int retryCount = 0;
void *tmpBuf = TransferBuffer;
ret = down_interruptible(&(pAd->UsbVendorReq_semaphore));
if (pAd->UsbVendorReqBuf)
{
ASSERT(TransferBufferLength <MAX_PARAM_BUFFER_SIZE);
tmpBuf = (void *)pAd->UsbVendorReqBuf;
NdisZeroMemory(pAd->UsbVendorReqBuf, TransferBufferLength);
if (RequestType == DEVICE_VENDOR_REQUEST_OUT)
NdisMoveMemory(tmpBuf, TransferBuffer, TransferBufferLength);
}
do {
if( RequestType == DEVICE_VENDOR_REQUEST_OUT)
ret=usb_control_msg(pObj->pUsb_Dev, usb_sndctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
else if(RequestType == DEVICE_VENDOR_REQUEST_IN)
ret=usb_control_msg(pObj->pUsb_Dev, usb_rcvctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES);
else
{
DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n"));
ret = -1;
}
retryCount++;
if (ret < 0) {
DBGPRINT(RT_DEBUG_OFF, ("#\n"));
RTMPusecDelay(5000);
}
} while((ret < 0) && (retryCount < MAX_RETRY_COUNT));
if ((pAd->UsbVendorReqBuf) && (RequestType == DEVICE_VENDOR_REQUEST_IN))
NdisMoveMemory(TransferBuffer, tmpBuf, TransferBufferLength);
up(&(pAd->UsbVendorReq_semaphore));
if (ret < 0) {
DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Index=0x%x\n",
ret, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index));
if (Request == 0x2)
DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value));
if ((TransferBuffer!= NULL) && (TransferBufferLength > 0))
hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength);
}
}
if (ret != -1)
return STATUS_SUCCESS;
else
return STATUS_UNSUCCESSFUL;
}