📄 usbdbgpdd.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#include <windows.h>
#include <usb200.h>
#include <usbtypes.h>
#include <oal.h>
#include <bsp.h>
#include <usbdbgddsi.h>
#include <usbdbgutils.h>
#include "Otgdev.h"
///=============================================================================
/// Discussions
///=============================================================================
/* Interrupt mode - USBDBG mode always runs in polling mode. Interrupt mode
// means interrupts will inform kernel kitl code that a packet has been received
// on a usb endpoint. Implementing interrupt mode improves kitl driver
// performance.
//
// To enable interrupt mode:
// 1. Enable interrupts for
// a. changes to bus state (reset, suspend, resume, attach, detach)
// b. setup packet on control endpoint, EP0
// c. OUT endpoints, EP3 (receiving endpoint)
// 2. Tie the USB function controller interrupt to KITL sysintr (kernel KITL
// code will then call Rndis_RecvFrame in usbdbgrndismdd to receive the
// packet).
*/
///
///=============================================================================
/// Global defines
///=============================================================================
// mandatory (refer usbdbgddsi.h for available zones)
UINT32 g_UsbDbgZones = USBDBG_ZONE_ERROR | USBDBG_ZONE_WARN |
USBDBG_ZONE_INFO;// | USBDBG_ZONE_RECV | USBDBG_ZONE_SEND | USBDBG_ZONE_VERBOSE |
//USBDBG_ZONE_FUNC;
DWORD g_LastRxPktStatus;
///=============================================================================
/// Macros
///=============================================================================
///=============================================================================
/// Local defines
///=============================================================================
// define product specific strings
#define MANUFACTURER L"Samsung"
#define PRODUCT L"USBDBG KITL for SMDK6410"
///=============================================================================
/// External functions
///=============================================================================
///=============================================================================
/// Static variables
///=============================================================================
static const USB_STRING m_Manufacturer =
{
sizeof(MANUFACTURER) + 2,
USB_STRING_DESCRIPTOR_TYPE,
MANUFACTURER
};
static const USB_STRING m_Product =
{
sizeof(PRODUCT) + 2,
USB_STRING_DESCRIPTOR_TYPE,
PRODUCT
};
///=============================================================================
/// Private Functions
///=============================================================================
///=============================================================================
/// Private Functions
///=============================================================================
#ifdef DEBUG
// print a setup packet request
static
void
PrintUDR(
USB_DEVICE_REQUEST* udr
)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (
L"usbpdd: Endpoint Zero Request bmRequestType = 0x%x, bRequest=0x%x,"
L"wValue=0x%x,wIndex=0x%x,wLength=0x%x\r\n",
udr->bmRequestType,
udr->bRequest,
udr->wValue,
udr->wIndex,
udr->wLength
));
}
#endif
static
void
DevStatChangeEvent(
DWORD source,
USBDBG_MSG* msg,
BYTE* msgBuf
)
{
// Attach
if ((source & INT_CONN_ID_STS_CNG) != 0)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (L"usbpdd: Device attach detected.\r\n"));
// Clear source bit
OUTREG32(GINTSTS, INT_CONN_ID_STS_CNG);
}
// Detach
if ((source & INT_DISCONN) != 0)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (L"usbpdd:Device detach detected.\r\n"));
// Clear source bit
OUTREG32(GINTSTS, INT_DISCONN);
*msg = USBDBG_MSG_BUS_EVENT_DETACH;
goto clean;
}
// Reset
if ((source & INT_RESET) != 0)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (L"usbpdd: Reset detected.\r\n"));
// Clear source bit
OUTREG32(GINTSTS, INT_RESET);
// Send the reset event only after the enumeration is done
// This way the MDD can query the current packet sizes selected
// based on the enumerated speed.
OTGDevice_HandleReset();
goto clean;
}
// Suspend
if ((source & INT_SUSPEND) != 0)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (L"usbpdd: Suspend detected.\r\n"));
// Clear source bit
OUTREG32(GINTSTS, INT_SUSPEND);
*msg = USBDBG_MSG_BUS_EVENT_SUSPEND;
goto clean;
}
// Resume
if ((source & INT_RESUME) != 0)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (L"usbpdd: Resume detected.\r\n"));
// Clear source bit
OUTREG32(GINTSTS, INT_RESUME);
// In the middle of a reset don't process other changes
*msg = USBDBG_MSG_BUS_EVENT_RESUME;
goto clean;
}
// Enum Done
if ((source & INT_ENUMDONE) != 0)
{
USBDBGMSG(USBDBG_ZONE_VERBOSE, (L"usbpdd:Device enumeration completed.\r\n"));
OTGDevice_HandleEnumDone();
// Clear source bit
OUTREG32(GINTSTS, INT_ENUMDONE);
// Signal the reset (and enum done) event to MDD
*msg = USBDBG_MSG_BUS_EVENT_RESET;
goto clean;
}
clean:
return;
}
static
void
ProcessSetupEvent(
USBDBG_MSG* msg,
BYTE* msgBuf
)
{
DWORD data[2];
USB_DEVICE_REQUEST *pSetup = (USB_DEVICE_REQUEST*)data;
data[0] = INREG32(EP_FIFO[0]);
data[1] = INREG32(EP_FIFO[0]);
#ifdef DEBUG
PrintUDR(pSetup);
#endif
// MDD doesn't call PDD back on these messages
if (pSetup->bmRequestType == 0)
{
switch(pSetup->bRequest)
{
case USB_REQUEST_SET_CONFIGURATION:
if (pSetup->wValue != 0)
{
// device is now in configured state
oOtgDev.m_uIsUsbOtgSetConfiguration = 1;
}
else
{
oOtgDev.m_uIsUsbOtgSetConfiguration = 0;
}
break;
case USB_REQUEST_SET_ADDRESS:
OTGDevice_SetAddress(pSetup->wValue);
break;
}
}
*msg = USBDBG_MSG_SETUP_PACKET;
memcpy(msgBuf, data, sizeof(data));
}
static
void
WaitForSetupXferDone()
{
DWORD iStatusRetry = 0;
DWORD LastCTLRegVal=0;
DWORD LastINTRegVal=0;
DWORD LastStatRegVal=0;
DWORD CTLRegVal=0;
DWORD INTRegVal=0;
DWORD StatRegVal=0;
DWORD pktsize;
DWORD i=0;
LastCTLRegVal = INREG32(DOEPCTL0);
LastINTRegVal = INREG32(DOEPINT0);
do
{
INTRegVal = INREG32(GINTSTS);
if (INTRegVal & INT_RX_FIFO_NOT_EMPTY)
{
StatRegVal = INREG32(GRXSTSR);
if ((StatRegVal & PKT_STATUS_MASK) == OUT_XFR_COMPLETED)
{
// status entry notifying completion of an earlier OUT transfer
// just pop it and drop, otherwise we will never get to the Setup Xfer completed status
StatRegVal = INREG32(GRXSTSP);
g_LastRxPktStatus = StatRegVal;
pktsize = (g_LastRxPktStatus & 0x7ff0)>>4;
if (pktsize > 0)
{
USBDBGMSG(USBDBG_ZONE_WARN, (L"UsbDbgPdd_RecvData: Waitloop: dwGrxStatus=0x%x (OUT_XFR_COMPLETED) Non zero packet size\r\n", g_LastRxPktStatus));
}
}
if ((StatRegVal & PKT_STATUS_MASK) == OUT_PKT_RECEIVED)
{
break;
}
if ((StatRegVal & PKT_STATUS_MASK) == SETUP_XFR_COMPLETED)
{
StatRegVal = INREG32(GRXSTSP);
g_LastRxPktStatus = StatRegVal;
pktsize = (g_LastRxPktStatus & 0x7ff0)>>4;
if (pktsize > 0)
{
USBDBGMSG(USBDBG_ZONE_WARN, (L"UsbDbgPdd_RecvData: Waitloop: dwGrxStatus=0x%x (SETUP_XFR_COMPLETED) Non zero packet size\r\n", g_LastRxPktStatus));
}
break;
}
}
iStatusRetry++;
} while (iStatusRetry < 10000);
CTLRegVal = INREG32(DOEPCTL0);
INTRegVal = INREG32(DOEPINT0);
if (!(INTRegVal & 0x8) && iStatusRetry < 10000)
{
do
{
INTRegVal = INREG32(DOEPINT0);
if(INTRegVal & 0x8)
{
break;
}
iStatusRetry++;
} while (iStatusRetry < 10000);
}
}
static
void
PowerOff(
)
{
}
static
void
PowerOn(
)
{
}
///=============================================================================
/// USBDBG_PDD DDSI (mdd/pdd) interface
///=============================================================================
//==============================================================================
// Description: Called by MDD when KITL or DLE call its pfnDeInit
//
// Arguments:
//
// Return Value:
//
extern "C"
void
UsbDbgPdd_DeInit(
)
{
// Disconnect hardware
OTGDevice_SetSoftDisconnect();
OTGDevice_DeInit();
}
//==============================================================================
// Description: Called by MDD during initialization to attach to USB bus.
//
// Arguments: Device descriptor returned by MDD to Host
//
// Return Value: TRUE if success else FALSE
//
extern "C"
BOOL
UsbDbgPdd_Connect(
USBDBG_DEVICE_DESCRIPTOR* pDeviceDesc
)
{
BOOL rc = FALSE;
USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbpdd: +UsbDbgPdd_Connect\r\n"));
// Connect the line
OTGDevice_ClearSoftDisconnect();
USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbpdd: -UsbDbgPdd_Connect\r\n"));
return rc;
}
//==============================================================================
// Description: Called by MDD to disconnect from USB bus
//
// Arguments: None
//
// Return Value: TRUE if success else FALSE
//
extern "C"
BOOL
UsbDbgPdd_Disconnect(
)
{
USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbpdd: +UsbDbgPdd_Disconnect\r\n"));
// Disconnect hardware
OTGDevice_SetSoftDisconnect();
USBDBGMSG(USBDBG_ZONE_FUNC, (L"usbpdd: -UsbDbgPdd_Disconnect\r\n"));
return TRUE;
}
//==============================================================================
// Description: Called by MDD to get some PDD specific properties. Look at
// USBDBG_PDD_IOCTL in file usbdbgifc.h
//
// Arguments: see below
//
// Ret Value: TRUE if IOCTL is supported else return FALSE. MDD will use
// the default implementation of an IOCTL if PDD returns FALSE.
//
extern "C"
BOOL
UsbDbgPdd_Ioctl(
DWORD ioControlCode, /* USBDBG_PDD_IOCTL */
LPVOID lpInBuffer, /* incoming buffer */
DWORD cbInBufferSize, /* incoming buffer size */
LPVOID lpOutBuffer, /* outgoing buffer */
DWORD cbOutBufferSize, /* outgoing buffer size */
LPDWORD lpBytesReturned /* outgoing buffer filled */
)
{
switch (ioControlCode)
{
// return maxpacket size for an endpoint
case USBDBG_PDD_IOCTL_ENDPT_MAXPACKETSIZE:
if (lpInBuffer && lpOutBuffer)
{
DWORD endPtNum = *((DWORD*)lpInBuffer);
if (endPtNum == 0)
{
*((UINT32*)lpOutBuffer) = oOtgDev.m_uControlEPMaxPktSize;
}
else
{
*((UINT32*)lpOutBuffer) = oOtgDev.m_uBulkInEPMaxPktSize;
}
}
return TRUE;
break;
case USBDBG_PDD_IOCTL_MANUFACTURER_STRING:
{
// lpOutBuffer = USB_STRING** ppManufacturer
if (lpOutBuffer)
*((USB_STRING**)(lpOutBuffer)) = (USB_STRING*) &m_Manufacturer;
return TRUE;
break;
}
case USBDBG_PDD_IOCTL_PRODUCT_STRING:
{
// lpOutBuffer = USB_STRING** ppProduct
if (lpOutBuffer)
*((USB_STRING**)(lpOutBuffer)) = (USB_STRING*) &m_Product;
return TRUE;
break;
}
}
// for rest of the properties use MDD's default
return FALSE;
}
//==============================================================================
// Description: MDD calls this API repeatedly to receive updates on USB bus
// states, receive, transmit complete events on endpoints and setup
// packet on Endpoint 0.
//
// Arguments: msg. (OUT) set to the appropriate USBDBG_MSG* defined in
// usbdbgddsi.h
// msgBuf. (OUT) set to setup packet or the endpoint number
// [64 bytes in length]
//
// Ret Value: ERROR_SUCCESS if no error else return error code.
//
extern "C"
DWORD
UsbDbgPdd_EventHandler(
USBDBG_MSG* msg,
BYTE* msgBuf
)
{
DWORD source;
DWORD epNum;
DWORD epIntNum;
DWORD pktsize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -