📄 pdd.c
字号:
//
// Function: UfnPdd_IsEndpointHalted
//
DWORD WINAPI UfnPdd_IsEndpointHalted(VOID *pPddContext,
DWORD endPoint,
BOOL *pHalted)
{
DWORD rc = ERROR_INVALID_FUNCTION;
USBFN_PDD *pPdd = pPddContext;
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum;
DEBUGMSG(ZONE_PDD, (L"UsbFnPdd_IsEndpointHalted %d\r\n", endPoint));
// Endpoint can't be zero
if (endPoint != 0)
{
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (!pPdd->ep[endPoint].dirRx)
{
epNum |= USBD_EP_NUM_DIRIN;
}
SelectEp(pPdd, epNum);
// Is EP halted?
*pHalted = ((INREG32(&pUSBDRegs->STAT_FLG) & USBD_STAT_HALTED) != 0);
// Deselect EP
DeselectEp(pPdd, epNum);
// Done
rc = ERROR_SUCCESS;
}
return rc;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_SendControlStatusHandshake
//
// Send the control status handshake.
//
DWORD WINAPI UfnPdd_SendControlStatusHandshake(VOID *pPddContext,
DWORD endPoint)
{
USBFN_PDD *pPdd = pPddContext;
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD epNum, stat;
DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - START\r\n"));
// Select EP
epNum = USBD_EP_NUM & endPoint;
if (pPdd->setupDirRx)
{
epNum |= USBD_EP_NUM_DIRIN;
}
SelectEp(pPdd, epNum);
// Get actual status
stat = INREG32(&pUSBDRegs->STAT_FLG);
DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - "
L"EndPoint %d (%s): STAT_FLG = 0x%04X\r\n", endPoint, pPdd->setupDirRx ? L"IN" : L"OUT", stat));
// Only send the handshake when the EndPoint is not stalled.
if ((stat & USBD_STAT_STALL) == 0)
{
// Clear & enable FIFO
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_EP);
OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_FIFO_EN);
}
else
{
DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - "
L"Not sending handshake because Endpoint %d is stalled\r\n", epNum));
}
// Deselect EP
DeselectEp(pPdd, epNum);
DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - END\r\n"));
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_InitiateRemoteWakeup
//
DWORD WINAPI UfnPdd_InitiateRemoteWakeup(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DEBUGMSG(ZONE_PDD, (L"UsbFnPdd_InitiateRemoteWakeup\r\n"));
SETREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_RMT_WKP);
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
#define PSZ_REG_CLIENT_DRIVER_PATH _T("\\Drivers\\USB\\FunctionDrivers")
#define PSZ_REG_DEFAULT_DEFAULT_CLIENT_DRIVER _T("DefaultClientDriver")
#define PSZ_REG_FRIENDLY_NAME _T("FriendlyName")
#define PSZ_REG_DEFAULT_CLIENT_KEY _T("DefaultClientKey")
#define MAX_LOADSTRING 100
static BOOL GetUfnDescription(HKEY hkClient,
LPTSTR pszDescription,
DWORD cchDescription)
{
DWORD dwType;
DWORD cbValue = sizeof(TCHAR) * cchDescription;
DWORD dwError = RegQueryValueEx(hkClient,
PSZ_REG_FRIENDLY_NAME,
NULL,
&dwType,
(PBYTE)pszDescription,
&cbValue);
pszDescription[cchDescription - 1] = 0; // Null-terminate
if ((dwError != ERROR_SUCCESS) || (dwType != REG_SZ))
{
// No description. Still return success, though.
pszDescription[0] = 0;
}
return TRUE;
}
static DWORD OpenFunctionKey(HKEY *phkFunctions)
{
// Determine which client driver to load
return RegOpenKeyEx(HKEY_LOCAL_MACHINE,
PSZ_REG_CLIENT_DRIVER_PATH,
0,
0,
phkFunctions);
}
static DWORD GetDefaultClientName(LPTSTR pszClientName)
{
HKEY hkFunctions = NULL;
DWORD cbData = MAX_LOADSTRING * sizeof(TCHAR);
DWORD dwType;
DWORD dwRet = OpenFunctionKey(&hkFunctions);
if (dwRet == ERROR_SUCCESS)
{
dwRet = RegQueryValueEx(hkFunctions,
PSZ_REG_DEFAULT_DEFAULT_CLIENT_DRIVER,
NULL,
&dwType,
(PBYTE)pszClientName,
&cbData);
if ((dwRet != ERROR_SUCCESS) || (dwType != REG_SZ))
{
// No client name. Still return success, though.
pszClientName[0] = 0;
}
}
if (hkFunctions)
{
RegCloseKey(hkFunctions);
}
return dwRet;
}
static DWORD ChangeDefaultClient(LPTSTR pszClientName)
{
DWORD dwRet;
HKEY hkFunctions = NULL;
dwRet = OpenFunctionKey(&hkFunctions);
if (dwRet == ERROR_SUCCESS)
{
dwRet = RegSetValueEx(hkFunctions,
PSZ_REG_DEFAULT_DEFAULT_CLIENT_DRIVER,
0,
REG_SZ,
(PBYTE)pszClientName,
(_tcslen(pszClientName) + 1) * sizeof(TCHAR));
}
if (hkFunctions)
{
RegCloseKey(hkFunctions);
}
return dwRet;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_IOControl
//
DWORD WINAPI UfnPdd_IOControl(VOID *pPddContext,
IOCTL_SOURCE source,
DWORD code,
UCHAR *pInBuffer,
DWORD inSize,
UCHAR *pOutBuffer,
DWORD outSize,
DWORD *pOutSize)
{
DWORD rc = ERROR_INVALID_PARAMETER;
USBFN_PDD *pPdd = pPddContext;
UFN_PDD_INFO info;
CE_BUS_POWER_STATE *pBusPowerState;
CEDEVICE_POWER_STATE devicePowerState;
switch (code)
{
case IOCTL_UFN_GET_PDD_INFO:
if (source != BUS_IOCTL)
{
break;
}
if (pOutBuffer == NULL || outSize < sizeof(UFN_PDD_INFO))
{
break;
}
info.InterfaceType = Internal;
info.BusNumber = 0;
info.dwAlignment = sizeof(DWORD);
if (!CeSafeCopyMemory(pOutBuffer, &info, sizeof(UFN_PDD_INFO)))
{
break;
}
rc = ERROR_SUCCESS;
break;
case IOCTL_BUS_GET_POWER_STATE:
if (source != MDD_IOCTL)
{
break;
}
if (pInBuffer == NULL || inSize < sizeof(CE_BUS_POWER_STATE))
{
break;
}
pBusPowerState = (CE_BUS_POWER_STATE*)pInBuffer;
if (!CeSafeCopyMemory(pBusPowerState->lpceDevicePowerState, &pPdd->m_CurrentPowerState, sizeof(CEDEVICE_POWER_STATE)))
{
break;
}
rc = ERROR_SUCCESS;
break;
case IOCTL_BUS_SET_POWER_STATE:
if (pInBuffer == NULL || inSize < sizeof(CE_BUS_POWER_STATE))
{
DEBUGMSG(ZONE_WARNING, (L"UfnPdd_IOControl() "
L"WARNING: Bad Parameter\r\n"));
break;
}
pBusPowerState = (CE_BUS_POWER_STATE*)pInBuffer;
if (!CeSafeCopyMemory(&devicePowerState, pBusPowerState->lpceDevicePowerState, sizeof(CEDEVICE_POWER_STATE)))
{
break;
}
DEBUGMSG(ZONE_POWER, (L"UfnPdd_IOControl() - "
L"Set Power State to D%d\r\n", (int)devicePowerState));
pPdd->m_NewPowerState = devicePowerState;
if (UpdateDevicePower(pPdd))
{
rc = ERROR_SUCCESS;
}
break;
case IOCTL_UFN_CHANGE_DEFAULT_CLIENT:
rc = ChangeDefaultClient((LPTSTR)pInBuffer);
break;
}
return rc;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_Deinit
//
DWORD WINAPI UfnPdd_Deinit(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
// Stop interrupt thread
if (pPdd->hIntrThread != NULL)
{
pPdd->exitIntrThread = TRUE;
SetEvent(pPdd->hIntrEvent);
WaitForSingleObject(pPdd->hIntrThread, INFINITE);
CloseHandle(pPdd->hIntrThread);
}
// Close interrupt handler
if (pPdd->hIntrEvent != NULL)
{
CloseHandle(pPdd->hIntrEvent);
pPdd->hIntrEvent = NULL;
}
// If parent bus is open, set hardware to D4 and close it
if (pPdd->hParentBus != NULL)
{
SetDevicePowerState(pPdd->hParentBus, D4, NULL);
CloseBusAccessHandle(pPdd->hParentBus);
pPdd->hParentBus = NULL;
}
// Unmap USBD controller registers
if (pPdd->pUSBDRegs != NULL)
{
MmUnmapIoSpace((VOID*)pPdd->pUSBDRegs, pPdd->memLen);
pPdd->pUSBDRegs = NULL;
}
// Release interrupt
if (pPdd->sysIntr != 0)
{
InterruptDisable(pPdd->sysIntr);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR,
&pPdd->sysIntr,
sizeof(pPdd->sysIntr),
NULL,
0,
NULL);
pPdd->sysIntr = 0;
}
// Delete critical section
DeleteCriticalSection(&pPdd->epCS);
// Free PDD context
LocalFree(pPdd);
AdvertiseInterface((const GUID *)DMCLASS_PROTECTEDBUSNAMESPACE, L"UsbFn",FALSE);
// Done
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_DeregisterDevice
//
// This function is called by MDD to move device to pre-registred state.
// On OMAP7xx we simply disable all end points.
//
DWORD WINAPI UfnPdd_DeregisterDevice(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD ep;
// Disable all RX, TX EPs
OUTREG32(&pUSBDRegs->EP0, 0);
for (ep = 0; ep < USBD_NONZERO_EP_COUNT; ep++)
{
OUTREG32(&pUSBDRegs->EP_RX[ep], 0);
OUTREG32(&pUSBDRegs->EP_TX[ep], 0);
}
return ERROR_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_Stop
//
// This function is called before UfnPdd_DeregisterDevice. It should de-attach
// device to USB bus (but we don't want disable interrupts because...)
//
DWORD WINAPI UfnPdd_Stop(VOID *pPddContext)
{
USBFN_PDD *pPdd = pPddContext;
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
CEDEVICE_POWER_STATE prevPowerState ;
DEBUGMSG(ZONE_PDD, (L"UfnPdd_Stop\r\n"));
prevPowerState = pPdd->m_CurrentPowerState;
if ((prevPowerState == D3) || (prevPowerState == D4))
{
pPdd->m_NewPowerState = D2;
UpdateDevicePower(pPdd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -