📄 rndis.c
字号:
default:
OALMSG(OAL_ERROR, (L"*** Unknown GET_DESCRIPTOR request:0x%x\r\n", HIBYTE(wType)));
fRet = FALSE;
break;
}
if (fRet) {
pRequest->eDir = EP0In;
pRequest->pucData = pucData;
pRequest->dwExpectedSize = pUdr->wLength;
pRequest->dwActualSize = min(wLength, pUdr->wLength);
pRequest->pfnNotification = NULL; // notification not required
pRequest->pvUser = NULL;
}
return fRet;
}
// parses the setup packet to determine if it is one of the two standard RNDIS requests
// and sets up a send or receive transfer request on EP0 if necessary
static BOOL PDD_DoVendorCommand(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
BOOL fRet = TRUE;
//
// RNDIS spec:: we should only be getting:
// - SEND_ENCAPSULATED_COMMAND or
// - GET_ENCAPSULATED_RESPONSE.
// So let's just look for these two, and bail out if it does
//not match..
//
switch (pUdr->bRequest) {
case SEND_ENCAPSULATED_COMMAND:
pRequest->eDir = EP0Out;
pRequest->pucData = (UCHAR *)(g_RndisKitlDev.EP0RxBuffer);
pRequest->dwExpectedSize = pUdr->wLength;
pRequest->dwActualSize = pUdr->wLength;
pRequest->pfnNotification = PDD_RecvNotification;
pRequest->pvUser = &(g_RndisKitlDev.EP0DataWrapper);
break;
case GET_ENCAPSULATED_RESPONSE:
pRequest->eDir = EP0In;
if (!IsListEmpty(&(g_RndisKitlDev.listTxRndisMessageQueue))) {
PLIST_ENTRY pLink;
PDATA_WRAPPER pDataWrapper;
pLink = RemoveHeadList(&(g_RndisKitlDev.listTxRndisMessageQueue));
pDataWrapper = CONTAINING_RECORD(pLink, DATA_WRAPPER, Link);
//KITLDEBUGMSG(MDDZONE, ("<0x%X\r\n", pDataWrapper));
pRequest->pucData = pDataWrapper->pucData;
pRequest->dwExpectedSize = pUdr->wLength;
pRequest->dwActualSize = pDataWrapper->dwDataSize;
pRequest->pfnNotification = PDD_SendNotification;
pRequest->pvUser = pDataWrapper;
g_RndisKitlDev.pEP0DataWrapper = pDataWrapper;
} else {
//
// RNDIS spec says if we have no data to send then
// send one byte packet set to 00 instead of stalling the
// pipe.
//
pRequest->pucData = &g_ucScratch;
pRequest->dwActualSize = sizeof(UCHAR);
pRequest->dwExpectedSize = pUdr->wLength;
pRequest->pfnNotification = NULL;
pRequest->pvUser = NULL;
}
break;
default:
fRet = FALSE;
break;
}
return fRet;
}
// sets up a packet receive transfer on EP1 (BULK OUT)
VOID SetupEP1Transfer()
{
// allocate data transfer for EP1
if (!g_pEP1DataWrapper) {
g_pEP1DataWrapper = MDDAllocDataWrapper();
if (!g_pEP1DataWrapper) {
OALMSG(OAL_ERROR, (L"No mem for RX DataWrapper\r\n"));
return;
}
g_pEP1DataWrapper->pucData = MDDAllocMem();
if (!g_pEP1DataWrapper->pucData) {
OALMSG(OAL_ERROR, (L"No mem for RX data\r\n"));
MDDFreeDataWrapper(g_pEP1DataWrapper);
return;
}
g_pEP1DataWrapper->dwDataSize = MAX_INCOMING_BUFFER;
}
// g_EP1Transfer.dwCallerPermissions;
g_EP1Transfer.pvBuffer = g_pEP1DataWrapper->pucData;
// g_EP1Transfer.dwBufferPhysicalAddress; // not used
g_EP1Transfer.cbBuffer = g_pEP1DataWrapper->dwDataSize;
g_EP1Transfer.cbTransferred = 0;
g_EP1Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; // Possible values are in usbfntypes.h
g_EP1Transfer.pvPddData = NULL;
g_EP1Transfer.pvPddTransferInfo = NULL;
g_EP1Transfer.dwFlags = 0;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 1, &g_EP1Transfer );
}
// parses the setup packet received on EP0
BOOL HandleSetupPacket(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
if (pUdr->bmRequestType & (USB_REQUEST_CLASS | USB_REQUEST_VENDOR)) {
if (PDD_DoVendorCommand(pUdr, pRequest)) {
// do nothing
} else {
OALMSG(OAL_ERROR, (
L"**** Unhandled verndor command 0x%x\r\n", pUdr->bRequest
));
pRequest->eDir = EP0Setup;
pRequest->pucData = NULL;
pRequest->dwExpectedSize = 0;
pRequest->dwActualSize = 0;
pRequest->pfnNotification = NULL;
pRequest->pvUser = NULL;
}
return TRUE;
}
// standard chapter 9 commands
pRequest->eDir = EP0Setup;
pRequest->pucData = NULL;
pRequest->dwExpectedSize = 0;
pRequest->dwActualSize = 0;
pRequest->pfnNotification = NULL;
pRequest->pvUser = NULL;
switch(pUdr->bRequest) {
case USB_REQUEST_GET_STATUS:
if (pUdr->bmRequestType == 0x82) {
// TODO: handle this
OALMSG(OAL_WARN, (L"***RequestType==0x82\r\n"));
// check for the stall bit
}
break;
case USB_REQUEST_CLEAR_FEATURE:
if (pUdr->bmRequestType == 0x02) {
// TODO: handle this
OALMSG(OAL_WARN, (L"***RequestType==0x02\r\n"));
}
break;
case USB_REQUEST_SET_FEATURE:
if (pUdr->bmRequestType == 0x02) {
// TODO: handle this
OALMSG(OAL_WARN, (L"***RequestType==0x02\r\n"));
}
break;
case USB_REQUEST_SET_ADDRESS:
// TODO: handle this
break;
case USB_REQUEST_GET_DESCRIPTOR:
if (PDD_GetDescriptor(pUdr, pRequest)) {
// do nothing
} else {
OALMSG(OAL_ERROR, (
L"*** UnHandled GET_DESCRIPTOR request:0x%x\r\n",
pUdr->wValue
));
}
break;
case USB_REQUEST_SET_DESCRIPTOR:
// TODO: handle this
break;
case USB_REQUEST_GET_CONFIGURATION:
// TODO: handle this
break;
case USB_REQUEST_SET_CONFIGURATION:
OALStall(5000);
// setup RX transfer on EP1
SetupEP1Transfer();
////pDev->ucConfigValue = (BYTE)pUdr->wValue;
break;
case USB_REQUEST_GET_INTERFACE:
// TODO: handle this
break;
case USB_REQUEST_SET_INTERFACE:
// TODO: handle this
break;
case USB_REQUEST_SYNC_FRAME:
// TODO: handle this
break;
default:
OALMSG(OAL_WARN, (
L"*** Unknown request 0x%x\r\n", pUdr->bRequest
));
}
return TRUE;
}
// indicates to the KITL MDD that a packet has been sent
void TxComplete(void)
{
RNDIS_KITLDEV *pRndisKitlDev = &g_RndisKitlDev;
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"SendPacket request completed! [%d bytes]\r\n",
g_EP2Transfer.cbTransferred
));
MddSendRndisPacketComplete(pRndisKitlDev->pTxDataWrapper);
OALMSG(OAL_ETHER&&OAL_FUNC, (L"Done\r\n"));
pRndisKitlDev->pTxDataWrapper = NULL;
}
// The USB FN PDD will call this function to notify it of various events (data sent/received,
// setup packet received, device addressed, reset, etc.
BOOL WINAPI NotifyHandler (
PVOID pvMddContext,
DWORD dwMsg,
DWORD dwParam
)
{
USB_DEVICE_REQUEST request;
EP0_REQUEST EP0Request;
STransfer *pTransfer;
switch( dwMsg )
{
case UFN_MSG_SETUP_PACKET:
request = *(USB_DEVICE_REQUEST*)(void*)dwParam;
g_udr = request;
if( !HandleSetupPacket( &g_udr, &EP0Request ) )
{
OALMSG(OAL_ERROR, (L"ERROR PARSING SETUP PACKET\r\n"));
}
memcpy(&g_RndisKitlDev.EP0Request, &EP0Request, sizeof(EP0Request));
g_RndisKitlDev.EP0Request.dwProcessed = 0;
g_RndisKitlDev.EP0Request.fCompleted = FALSE;
if (g_RndisKitlDev.EP0Request.eDir != EP0Setup) {
g_EP0DataWrapper.pucData = g_RndisKitlDev.EP0Request.pucData;
g_EP0DataWrapper.dwDataSize = g_RndisKitlDev.EP0Request.dwActualSize;
// g_EP2Transfer.dwCallerPermissions;
g_EP0Transfer.pvBuffer = g_EP0DataWrapper.pucData;
// g_EP2Transfer.dwBufferPhysicalAddress; // not used
g_EP0Transfer.cbBuffer = g_EP0DataWrapper.dwDataSize;
g_EP0Transfer.cbTransferred = 0;
g_EP0Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; // Possible values are in usbfntypes.h
g_EP0Transfer.pvPddData = NULL;
g_EP0Transfer.pvPddTransferInfo = NULL;
if (g_RndisKitlDev.EP0Request.eDir == EP0In) {
OALMSG(OAL_ETHER&&OAL_FUNC, (L"Got SETUP IN packet\r\n"));
g_EP0Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
g_EP0TransferState = TS_SENDING_MESSAGE;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer );
}
else
{
OALMSG(OAL_ETHER&&OAL_FUNC, (L"Got SETUP OUT packet.\r\n"));
g_EP0Transfer.dwFlags = 0;
g_EP0TransferState = TS_RECEIVING_MESSAGE;
g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer );
}
}
else
{
OALMSG(OAL_ETHER&&OAL_FUNC, (
L"Got SETUP <NO DATA: %x %x %x %x %x> packet.\r\n",
g_udr.bmRequestType, g_udr.bRequest, g_udr.wValue, g_udr.wIndex,
g_udr.wLength
));
// Send the SETUP ACK packet
g_EP0TransferState = TS_IDLE;
g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
}
break;
case UFN_MSG_TRANSFER_COMPLETE:
pTransfer = (STransfer *)dwParam;
if( pTransfer == &g_EP0Transfer )
{
switch( g_EP0TransferState )
{
case TS_RECEIVING_MESSAGE:
g_EP0TransferState = TS_IDLE;
OALMSG(OAL_ETHER&&OAL_FUNC, (L"Done receiving data.\r\n"));
g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
if (g_RndisKitlDev.EP0Request.pfnNotification) {
OALMSG(OAL_ETHER&&OAL_FUNC, (L"Received a message!\r\n"));
g_RndisKitlDev.EP0Request.pfnNotification(&g_RndisKitlDev.EP0Request, g_RndisKitlDev.EP0Request.pvUser);
}
memset(&g_RndisKitlDev.EP0Request, 0, sizeof (g_RndisKitlDev.EP0Request));
break;
case TS_SENDING_MESSAGE:
OALMSG(OAL_ETHER&&OAL_FUNC, (L"Done sending data.\r\n"));
g_EP0TransferState = TS_IDLE;
g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
if (g_RndisKitlDev.EP0Request.pfnNotification) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -