📄 usbdbgpdd.cpp
字号:
DWORD epIntStatus;
BOOL fProcessed = FALSE;
*msg = USBDBG_MSG_NOMSG; //no msg by default
// Get interrupt source and clear it
source = INREG32(GINTSTS);
if (source == 0)
goto clean;
// Device state change?
if ((source & (INT_RESET | INT_RESUME | INT_SUSPEND | INT_DISCONN | INT_CONN_ID_STS_CNG | INT_ENUMDONE)) != 0)
{
// Handle device state change
DevStatChangeEvent(source, msg, msgBuf);
// don't process other interrupts
goto clean;
}
// RX interrupt
if (source & INT_RX_FIFO_NOT_EMPTY)
{
// Pop packet status
g_LastRxPktStatus = INREG32(GRXSTSP);
if (((g_LastRxPktStatus & PKT_STATUS_MASK) == SETUP_XFR_COMPLETED))
{
pktsize = (g_LastRxPktStatus & 0x7ff0)>>4;
if (pktsize > 0)
{
USBDBGMSG(USBDBG_ZONE_WARN, (L"UsbDbgPdd_EventHandler: RX_FIFO_NOT_EMPTY dwGrxStatus=0x%x (SETUP Completed) Non zero packet size\r\n", g_LastRxPktStatus));
}
}
else if ((g_LastRxPktStatus & PKT_STATUS_MASK) == OUT_PKT_RECEIVED)
{
// get endpoint
epNum = g_LastRxPktStatus & 0xF;
// tell MDD pkt received on EPn
*msg = USBDBG_MSG_EP_RX_PKT;
*((DWORD*)(msgBuf)) = epNum;
fProcessed = TRUE;
}
else if ((g_LastRxPktStatus & PKT_STATUS_MASK) == SETUP_PKT_RECEIVED)
{
// Setup Packet
ProcessSetupEvent(msg, msgBuf);
fProcessed = TRUE;
}
if (fProcessed)
{
goto clean;
}
}
// IN Endpoint interrupt
if (source & INT_IN_EP)
{
// Find the endpoint number
epIntNum = INREG32(DAINT);
epNum = 0;
while(!(epIntNum & 1))
{
epIntNum = epIntNum >> 1;
epNum++;
}
epIntStatus = INREG32(DIEPINT[epNum]);
if ((epIntStatus & TRANSFER_DONE) &&
(EndPointsInfo[epNum].EndPtAttributes != 3)) // Need not indicate TRANSFER_DONE for INT IN ep
{
// tell MDD pkt transmitted on EPn
*msg = USBDBG_MSG_EP_TX_PKT;
*((DWORD*)(msgBuf)) = epNum;
}
// Clear source bit
OUTREG32(DIEPINT[epNum], epIntStatus);
goto clean;
}
// OUT Endpoint interrupt
if (source & INT_OUT_EP)
{
// Find the endpoint number
epIntNum = INREG32(DAINT);
epIntNum = epIntNum >> 16;
epNum = 0;
while(!(epIntNum & 1))
{
epIntNum = epIntNum >> 1;
epNum++;
}
epIntStatus = INREG32(DOEPINT[epNum]);
// Clear source bit
OUTREG32(DOEPINT[epNum], epIntStatus);
goto clean;
}
clean:
return ERROR_SUCCESS;
}
//==============================================================================
// Description: MDD calls this function to
// 1) start a receive transfer on an endpoint
// 2) receive data from an endpoint after getting endpoint rx
// interrupt via UsbDbgPdd_EventsHandler
//
// Start a receive transfer: when transferFlags =
// USBDBG_MDD_TRANSFER_START, start a receive transfer on the
// endpt. Do not read value from the receive FIFO yet.
//
// Receive data: when transferFlags != USBDBG_MDD_TRANSFER_START,
// read the data from FIFO and write to pBuffer.
// If buffer is filled up completely or a short packet (packet size
// smaller than maxpktsize) is received, disable the receive FIFO
// else reenable the FIFO.
//
// Arguments: epNum. endpt to receive data on.
// USBDBGRNDISMDD endpts: 0, 1: INT IN, 2: BULK IN, 3: BULK OUT
// USBDBGSERMDD endpts: 0, 1: BULK OUT, 2: BULK IN
// pBuffer. buffer data is received in.
// cbBufLen. size of pBuffer. If buffer is completely filled
// disable the RX FIFO and set pTransferStatus =
// USBDBG_PDD_TRANSFER_COMPLETE. If a short packet is received,
// disable RX FIFO and set pTransferStatus =
// USBDBG_PDD_TRANSFER_COMPLETE. Else reenable the FIFO for
// next packet.
// transferFlags. Bitwise OR of flags.
// if transferFlags == USBDBG_MDD_TRANSFER_START start the
// transfer. do not return data.
// USBDBG_MDD_EP0_STATUS_STAGE marks a receive for EP0 status
// stage.
// pTransferStatus. OUT. set pTransferStatus =
// USBDBG_PDD_TRANSFER_COMPLETE when pBuffer is filled up or
// a short packet is received.
//
// Ret Value: count in bytes of data received. return -1 if error (MDD cancels
// the transfer if -1 is returned)
//
extern "C"
DWORD
UsbDbgPdd_RecvData(
DWORD epNum,
PBYTE pBuffer,
DWORD cbBufLen,
DWORD transferFlags,
DWORD* pTransferStatus
)
{
DWORD count, remain;
DWORD dwData;
DWORD index;
DWORD cbRecvd = 0;
DWORD cbFullPkt = 0;
DWORD GrxStatus;
// just enable RX FIFO and return if transfer is starting
// MDD is not expecting data at this time
if (transferFlags & USBDBG_MDD_TRANSFER_START)
{
if (((g_LastRxPktStatus & PKT_STATUS_MASK) == SETUP_PKT_RECEIVED) &&
(epNum == 0))
{
// MDD is expecting an OUT packet on EP0 right after receiving a setup packet.
// This happens for USB RNDIS because the SEND_ENCAPSULATED_COMMAND message is
// sent as a SETUP packet with the command details coming in as OUT packets on EP0
// Let's wait here to ensure that the setup transaction is completed and/or OUT EP is ready
// Otherwise, some data munching is observed on Rx FIFO
WaitForSetupXferDone();
}
// set transfer sizes
OTGDevice_SetOutEpXferSize(epNum, 1); // 1 packet
// Enable endpoint, clear NAK bit
SETREG32(DOEPCTL[epNum], (DEPCTL_EPENA |DEPCTL_CNAK));
goto clean;
}
// We get to this point because a packet was RX on epNum
// (HW automatically disables RX FIFO after receiving packet)
GrxStatus = g_LastRxPktStatus;
ASSERT((GrxStatus & OUT_PKT_RECEIVED) == OUT_PKT_RECEIVED);
if((GrxStatus & OUT_PKT_RECEIVED) != OUT_PKT_RECEIVED)
USBDBGMSG(USBDBG_ZONE_WARN, (L"usbpdd:UsbDbgPdd_RecvData: !OUT_PKT_RECEIVED\r\n"));
count = (GrxStatus & 0x7ff0)>>4;
// if expected data = 0 bytes, we just received it.
// do not read FIFO. return. ?? since MDD buffer is full disable RX FIFO
if (cbBufLen == 0)
{
if(count != 0)
USBDBGMSG(USBDBG_ZONE_WARN, (L"usbpdd:UsbDbgPdd_RecvData: count != 0 for a zero byte packet\r\n"));
goto clean;
}
// Read data
remain = count;
while (remain > 4)
{
dwData = INREG32(EP_FIFO[epNum]);
pBuffer[0] = (UCHAR)dwData;
pBuffer[1] = (UCHAR)(dwData >> 8);
pBuffer[2] = (UCHAR)(dwData >> 16);
pBuffer[3] = (UCHAR)(dwData >> 24);
pBuffer += 4;
remain -= 4;
}
if (remain > 0)
{
dwData = INREG32(EP_FIFO[epNum]);
for (index=0; index<remain; index++)
{
pBuffer[index] = (UCHAR)(dwData >> (index*8));
}
}
// set number of bytes received
cbRecvd = count;
// check to make sure data recvd < buffer length (should not happen)
if (cbRecvd > cbBufLen)
{
USBDBGMSG(USBDBG_ZONE_ERROR, (
L"usbpdd:ERROR: rx %d bytes > buflen=%d bytes\r\n",
cbRecvd, cbBufLen));
cbRecvd = 0;
goto clean;
}
// enable RX FIFO/endpoint if MDD receive buffer is not full
// and short packet not received
cbFullPkt = (epNum == 0) ? oOtgDev.m_uControlEPMaxPktSize : oOtgDev.m_uBulkOutEPMaxPktSize;
if ((cbBufLen > cbRecvd) && (cbRecvd == cbFullPkt))
{
// set transfer sizes
OTGDevice_SetOutEpXferSize(epNum, 1); // 1 packet
// Enable endpoint
SETREG32(DOEPCTL[epNum], (DEPCTL_EPENA |DEPCTL_CNAK));
}
else
{
*pTransferStatus |= USBDBG_PDD_TRANSFER_COMPLETE;
}
clean:
USBDBGMSG(USBDBG_ZONE_FUNC, (
L"usbpdd:ep%d recv %d bytes flags=0x%x\r\n",
epNum, cbRecvd, transferFlags
));
return cbRecvd;
}
//==============================================================================
// Description: MDD calls this function to send data over an endpoint. Send
// max data over the endpoint and return cb of data sent.
//
// Arguments: epNum. endpt to send data on.
// USBDBGRNDISMDD endpts: 0, 1: INT IN, 2: BULK IN, 3: BULK OUT
// USBDBGSERMDD endpts: 0, 1: BULK OUT, 2: BULK IN
// pBuffer. buffered data to send. Note: **this is not aligned.**
// cbBufLen. size of pBuffer.
// transferFlags. Bitwise OR.
// USBDBG_EP0_STATUS_STAGE marks a send for EP0 status
// stage.
// pTransferStatus. OUT. set pTransferStatus =
// USBDBG_PDD_TRANSFER_COMPLETE when MDD should not wait for a
// TX interrupt which signals that this packet has been
// transferred
//
// Ret Value: count in bytes of data sent. if error returns -1 (current
// transfer will be cancelled).
//
extern "C"
DWORD
UsbDbgPdd_SendData(
DWORD epNum,
PBYTE pBuffer,
DWORD cbLength,
DWORD transferFlags,
DWORD* pTransferStatus
)
{
DWORD data;
DWORD index;
volatile DWORD dwRegVal;
DWORD maxpkt = (epNum == 0) ? oOtgDev.m_uControlEPMaxPktSize : oOtgDev.m_uBulkInEPMaxPktSize;
DWORD pktCount = 0;
DWORD cbDataToSend = cbLength > maxpkt ? maxpkt : cbLength;
DWORD cbDataSent = cbDataToSend;
USBDBGMSG(USBDBG_ZONE_FUNC, (
L"usbpdd (++):ep%d To send %d bytes flags=0x%x maxpkt=%d\r\n",
epNum, cbLength, transferFlags, maxpkt
));
// clear all interrupts for this endpoint
dwRegVal = INREG32(DIEPINT[epNum]);
OUTREG32(DIEPINT[epNum], dwRegVal);
// Set the transfer sizes
OUTREG32(DIEPTSIZ[epNum], (1<<19)|(cbDataToSend<<0)); // packet count = 1, xfr size
// Enable endpoint, clear NAK bit
SETREG32(DIEPCTL[epNum], (DEPCTL_EPENA |DEPCTL_CNAK));
// Write data to FIFO
while (cbDataSent >= 4)
{
data = (pBuffer[3] << 24) | (pBuffer[2] << 16) | (pBuffer[1] << 8) | pBuffer[0];
OUTREG32(EP_FIFO[epNum], data);
pBuffer += 4;
cbDataSent -= 4;
}
if (cbDataSent > 0)
{
data = 0;
for (index=0; index<cbDataSent; index++)
{
data |= (pBuffer[0] << (index*8));
pBuffer++;
}
OUTREG32(EP_FIFO[epNum], data);
}
// for interrupt IN EP, indicate completion now.
if (EndPointsInfo[epNum].EndPtAttributes == 3)
{
*pTransferStatus |= USBDBG_PDD_TRANSFER_COMPLETE;
}
// issued a transfer on ENDPTN
USBDBGMSG(USBDBG_ZONE_FUNC, (
L"usbpdd (--):ep%d send %d bytes flags=0x%x\r\n",
epNum, cbDataToSend, transferFlags
));
return cbDataToSend;
}
//==============================================================================
// Description: MDD calls this function to send miscellaneous commands to pdd.
// Look at usbdbgddsi.h for USBDBG_CMD_* commands
//
// Arguments: cmd: an USBDBG_CMD_* command
// epNum: logical endpoint number
// epDir: endpoint direction (ENDPT_DIR_IN or ENDPT_DIR_OUT)
//
// Ret Value: Ignored.
//
extern "C"
DWORD
UsbDbgPdd_SendCmd(
USBDBG_CMD cmd,
DWORD epNum,
USBDBG_ENDPTDIR epDir
)
{
DWORD dwRegVal;
USBDBGMSG(USBDBG_ZONE_FUNC, (L"+UsbDbgPdd_SendCmd\r\n"));
switch (cmd)
{
// abort transfer on an endpt
case USBDBG_CMD_TRANSFER_ABORT:
{
if (epNum != 0)
{
if (epDir == ENDPT_DIR_IN)
{
if (INREG32(DIEPCTL[epNum]) & DEPCTL_EPENA)
{
OUTREG32(DIEPCTL[epNum], DEPCTL_EPDIS);
do
{
dwRegVal = INREG32(DIEPINT[epNum]);
}while( (dwRegVal & 0x2) == 0);
}
}
else
{
if (INREG32(DOEPCTL[epNum]) & DEPCTL_EPENA)
{
OUTREG32(DOEPCTL[epNum], DEPCTL_EPDIS);
do
{
dwRegVal = INREG32(DIEPINT[epNum]);
}while( (dwRegVal & 0x2) == 0);
}
}
}
break;
}
default:
break;
}
USBDBGMSG(USBDBG_ZONE_FUNC, (L"-UsbDbgPdd_SendCmd\r\n"));
return ERROR_SUCCESS;
}
//==============================================================================
// Description: MDD calls this function when OAL calls IOCTL_KITL_POWER_CALL to
// suspend or resume the device. When OAL calls suspend,
// fPowerOff=TRUE. When OAL calls resume, fPowerOff=FALSE.
// PDD should take appropriate action here to tear down the USB
// debug connection (can be as simple as logically detaching USB
// cable) or reenable the USB Debug connection (can be as simple
// as logically attaching USB cable).
//
// Arguments: When OAL calls suspend, fPowerOff=TRUE.
// When OAL calls resume, fPowerOff=FALSE.
//
// Ret Value:
//
extern "C"
void
UsbDbgPdd_SetPower(
BOOL fPowerOff
)
{
if (fPowerOff)
PowerOff();
else
PowerOn();
}
//==============================================================================
// Description: PDD should always implement this function. MDD calls it during
// initialization to fill up the function table with rest of the
// DDSI functions.
//
// Arguments: pMddIfc (with MDD's version number)
// pPddIfc (the function table to be filled)
// pDeviceDesc (usb device descriptor)
//
// Ret Value: ERROR_SUCCESS.
//
extern "C"
DWORD
UsbDbgPdd_Init(
USBDBG_MDD_INTERFACE_INFO* pMddIfc,
USBDBG_PDD_INTERFACE_INFO* pPddIfc,
USBDBG_DEVICE_DESCRIPTOR* pDeviceDesc
)
{
DWORD rc = E_FAIL;
USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbpdd: +UsbDbgPdd_Init\r\n"));
//1. fill up pddifc table
//
pPddIfc->version = 2;
pPddIfc->pfnDeinit = UsbDbgPdd_DeInit;
pPddIfc->pfnConnect = UsbDbgPdd_Connect;
pPddIfc->pfnDisconnect = UsbDbgPdd_Disconnect;
pPddIfc->pfnIoctl = UsbDbgPdd_Ioctl;
pPddIfc->pfnEventHandler = UsbDbgPdd_EventHandler;
pPddIfc->pfnRecvData = UsbDbgPdd_RecvData;
pPddIfc->pfnSendData = UsbDbgPdd_SendData;
pPddIfc->pfnSendCmd = UsbDbgPdd_SendCmd;
pPddIfc->pfnSetPower = UsbDbgPdd_SetPower;
//2. init local variables
//
g_LastRxPktStatus = 0;
//3. initialize hardware
//
OTGDevice_Init();
//4. init end points
//
if (!OTGDevice_InitEndPts(pDeviceDesc))
goto clean;
rc = ERROR_SUCCESS;
clean:
USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbpdd: -UsbDbgPdd_Init\r\n"));
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -