📄 ufnmdd.cpp
字号:
pPipe->Reserve(Speed, TRUE, pInterface->Descriptor.bInterfaceNumber,
dwEndpoint, &pEndpoint->Descriptor);
break;
}
}
if (dwPipe == pContext->PddInfo.dwEndpointCount) {
DEBUGMSG(ZONE_ERROR, (_T("%s Endpoint descriptor 0x%x cannot be supported\r\n"),
pszFname, dwEndpoint));
dwRet = ERROR_INVALID_PARAMETER;
goto EXIT;
}
}
dwRet = ERROR_SUCCESS;
EXIT:
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s Cannot support provided %s speed interface\r\n"),
pszFname, GetSpeedString(Speed)));
}
FUNCTION_LEAVE_MSG();
return dwRet;
}
static
DWORD
IsDeviceSupportable(
PUFN_MDD_CONTEXT pContext,
UFN_BUS_SPEED Speed,
PUSB_DEVICE_DESCRIPTOR pDeviceDesc,
PUFN_CONFIGURATION pConfig
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_INVALID_PARAMETER;
PREFAST_DEBUGCHK(pContext);
PREFAST_DEBUGCHK(pDeviceDesc);
PREFAST_DEBUGCHK(pConfig);
DEBUGCHK(IS_VALID_SPEED(Speed));
// Only support a client with one configuration
if (pDeviceDesc->bNumConfigurations != 1) {
DEBUGMSG(ZONE_ERROR, (_T("%s Only support one configuration\r\n"),
pszFname));
goto EXIT;
}
if ( (pConfig->Descriptor.bNumInterfaces == 0) || (pConfig->pInterfaces == NULL) ) {
DEBUGMSG(ZONE_ERROR, (_T("%s No interface provided\r\n"), pszFname));
goto EXIT;
}
// Make sure that the PDD can handle the configuration as a whole before giving it
// each endpoint at a time.
dwRet = pContext->PddInfo.pfnIsConfigurationSupportable(
pContext->PddInfo.pvPddContext, Speed, pConfig);
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s PDD cannot support the configuration\r\n"),
pszFname));
goto EXIT;
}
// Ensure that the specified endpoint 0 can be supported in both high
// and full speed modes.
dwRet = IsEndpointZeroSupportable(pContext, pDeviceDesc, Speed);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
// Verify that the endpoints in every interface can be supported.
DWORD cEndpoints;
cEndpoints = 0;
DWORD dwInterface;
for (dwInterface = 0; dwInterface < pConfig->Descriptor.bNumInterfaces; ++dwInterface) {
PUFN_INTERFACE pInterface = &pConfig->pInterfaces[dwInterface];
cEndpoints += pInterface->Descriptor.bNumEndpoints;
if (cEndpoints >= pContext->PddInfo.dwEndpointCount) {
DEBUGMSG(ZONE_ERROR, (_T("%s Not enough endpoints for client\r\n"),
pszFname));
dwRet = ERROR_INVALID_PARAMETER;
goto EXIT;
}
dwRet = IsInterfaceSupportable(pContext, pInterface, Speed, pConfig->Descriptor.bConfigurationValue);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
}
// At this point, the device descriptors have been validated and
// adjusted with for endpoint 0.
pContext->pPipes[0].Reserve(BS_FULL_SPEED, TRUE, 0, 0, NULL);
pContext->pPipes[0].Reserve(BS_HIGH_SPEED, TRUE, 0, 0, NULL);
EXIT:
FUNCTION_LEAVE_MSG();
return dwRet;
}
static
VOID
AdjustDeviceDesc(
PUFN_MDD_CONTEXT pContext,
PUSB_DEVICE_DESCRIPTOR pDeviceDesc
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pContext);
PREFAST_DEBUGCHK(pDeviceDesc);
DWORD bcdUSB;
DWORD dwErr = ReadRegDword(pContext->hKey, PSZ_REG_USB_RELEASE, FALSE,
&bcdUSB);
if (dwErr == ERROR_SUCCESS) {
DEBUGMSG(ZONE_FUNCTION, (_T("%s Using bcdUSB of 0x%04x\r\n"),
pszFname, bcdUSB));
pDeviceDesc->bcdUSB = (WORD) bcdUSB;
}
FUNCTION_LEAVE_MSG();
}
// Register the descriptors with the MDD and PDD.
DWORD
WINAPI
UfnMdd_RegisterDevice(
UFN_HANDLE hDevice,
PUSB_DEVICE_DESCRIPTOR pHighSpeedDeviceDesc,
PUFN_CONFIGURATION pHighSpeedConfig,
PUSB_DEVICE_DESCRIPTOR pFullSpeedDeviceDesc,
PUFN_CONFIGURATION pFullSpeedConfig,
PCUFN_STRING_SET pStringSets,
DWORD cStringSets
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet = ERROR_INVALID_PARAMETER;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
BOOL fTookCS = FALSE;
VERIFY_PCONTEXT();
EnterCriticalSection(&pContext->csMddAccess);
fTookCS = TRUE;
if ( (pHighSpeedDeviceDesc == NULL) || (pFullSpeedDeviceDesc == NULL) ||
(pHighSpeedConfig == NULL) || (pFullSpeedConfig == NULL) ) {
DEBUGMSG(ZONE_ERROR, (_T("%s Invalid parameter\r\n"), pszFname));
goto EXIT;
}
if (pContext->fRunning) {
// Must stop device before registering
DEBUGMSG(ZONE_ERROR, (_T("%s Device is still running\r\n"), pszFname));
dwRet = ERROR_BAD_ENVIRONMENT;
goto EXIT;
}
if (pContext->fRegistered) {
// Must deregister before re-registering
DEBUGMSG(ZONE_ERROR, (_T("%s Device is still registered\r\n"), pszFname));
dwRet = ERROR_BAD_ENVIRONMENT;
goto EXIT;
}
__try {
// Verify that the device and config descriptors are supportable.
dwRet = IsDeviceSupportable(pContext, BS_FULL_SPEED, pFullSpeedDeviceDesc,
pFullSpeedConfig);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
if (PddSupportsHighSpeed(pContext)) {
dwRet = IsDeviceSupportable(pContext, BS_HIGH_SPEED, pHighSpeedDeviceDesc,
pHighSpeedConfig);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
}
// Adjust the full speed descriptor as necessary according to the registry
AdjustDeviceDesc(pContext, pFullSpeedDeviceDesc);
// Copy our structures.
dwRet = CopyUsbStructs(pContext, pHighSpeedDeviceDesc, pHighSpeedConfig,
pFullSpeedDeviceDesc, pFullSpeedConfig, pStringSets, cStringSets);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
dwRet = pContext->PddInfo.pfnRegisterDevice(
pContext->PddInfo.pvPddContext,
&pContext->HighSpeedDeviceDesc,
&pContext->HighSpeedConfig,
pContext->pHighSpeedConfigDesc,
&pContext->FullSpeedDeviceDesc,
&pContext->FullSpeedConfig,
pContext->pFullSpeedConfigDesc,
pContext->pStringSets,
pContext->cStringSets
);
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s Could not RegisterDevice with PDD\r\n"), pszFname));
goto EXIT;
}
pContext->fRegistered = TRUE;
DEBUGMSG(ZONE_INIT, (_T("%s Device registered\r\n"), pszFname));
dwRet = ERROR_SUCCESS;
} // __try
__except(EXCEPTION_EXECUTE_HANDLER) {
DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
dwRet = ERROR_INVALID_PARAMETER;
}
EXIT:
if (dwRet != ERROR_SUCCESS) {
DEBUGCHK(pContext->fRegistered == FALSE);
FreeUsbStructs(pContext);
ResetPipeStatusTable(pContext);
}
FUNCTION_LEAVE_MSG();
if (fTookCS) {
LeaveCriticalSection(&pContext->csMddAccess);
}
return dwRet;
}
// Attach the device to the USB bus and register notification routines.
DWORD
WINAPI
UfnMdd_Start(
UFN_HANDLE hDevice,
LPUFN_NOTIFY lpDeviceNotify,
PVOID pvDeviceNotifyParameter,
PUFN_PIPE phDefaultPipe
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
PCPipe pPipeZero = NULL;
BOOL fTookCS = FALSE;
VERIFY_PCONTEXT();
RETAILMSG(1,(TEXT("############# UfnMdd_Start: modified mx31 library ################\n\r")));
EnterCriticalSection(&pContext->csMddAccess);
fTookCS = TRUE;
if (phDefaultPipe == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s Invalid parameter\r\n"), pszFname));
dwRet = ERROR_INVALID_PARAMETER;
goto EXIT;
}
if (!pContext->fRegistered) {
DEBUGMSG(ZONE_ERROR, (_T("%s Device has not been registered\r\n"),
pszFname));
dwRet = ERROR_BAD_ENVIRONMENT;
goto EXIT;
}
pContext->lpDeviceNotify = lpDeviceNotify;
pContext->pvDeviceNotifyParameter = pvDeviceNotifyParameter;
// For endpoint 0, transfer type and direction are ignored. Since
// we do not know what speed bus this will be hooked up to, we use
// the high speed endpoint 0 packet size.
USB_ENDPOINT_DESCRIPTOR EndpointDesc;
InitializeEndpointZeroDescriptor(pContext,
pContext->FullSpeedDeviceDesc.bMaxPacketSize0, &EndpointDesc);
pPipeZero = &pContext->pPipes[0];
dwRet = pPipeZero->Open(BS_FULL_SPEED, &EndpointDesc);
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s Could not init endpoint 0\r\n"), pszFname));
goto EXIT;
}
DEBUGCHK(pPipeZero->IsReserved(BS_FULL_SPEED));
// Return handle to default pipe
__try {
*phDefaultPipe = pPipeZero;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
dwRet = ERROR_INVALID_PARAMETER;
}
pContext->pUfnBus->SetChildDevicePowerState(D0);
dwRet = pContext->PddInfo.pfnStart(pContext->PddInfo.pvPddContext);
if (dwRet != ERROR_SUCCESS) {
goto EXIT;
}
DEBUGMSG(ZONE_INIT, (_T("%s Function controller running\r\n"), pszFname));
pContext->fRunning = TRUE;
EXIT:
if (dwRet != ERROR_SUCCESS) {
if (IS_VALID_MDD_CONTEXT(pContext)) {
if (pPipeZero && pPipeZero->IsOpen()) {
pPipeZero->Close();
}
pContext->lpDeviceNotify = NULL;
pContext->pvDeviceNotifyParameter = NULL;
}
}
FUNCTION_LEAVE_MSG();
if (fTookCS) {
LeaveCriticalSection(&pContext->csMddAccess);
}
return dwRet;
}
DWORD
DoStop(
PUFN_MDD_CONTEXT pContext
)
{
SETFNAME();
EnterCriticalSection(&pContext->csMddAccess);
FUNCTION_ENTER_MSG();
// At this point, the client should not be able to receive notification callbacks
pContext->fRunning = FALSE;
pContext->lpDeviceNotify = NULL;
pContext->pvDeviceNotifyParameter = NULL;
// Close all the pipes except for EP 0.
for (DWORD dwPipe = 1; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
PCPipe pPipe = &pContext->pPipes[dwPipe];
if (pPipe->IsOpen()) {
VERIFY(pPipe->Close()); // Why would this fail?
}
}
// Leave the critical section while calling PDD's Stop, since it will wait
// for the IST to close, but the IST might be in the process of calling the
// MDD's notification routine which also uses this critical section.
LeaveCriticalSection(&pContext->csMddAccess);
DWORD dwRet = pContext->PddInfo.pfnStop(pContext->PddInfo.pvPddContext);
DEBUGCHK(dwRet == ERROR_SUCCESS); // Why would this fail?
EnterCriticalSection(&pContext->csMddAccess);
// Close endpoint 0.
DEBUGCHK(pContext->pPipes[0].IsOpen());
VERIFY(pContext->pPipes[0].Close()); // Why would this fail?
pContext->pUfnBus->SetChildDevicePowerState(D4);
FUNCTION_LEAVE_MSG();
LeaveCriticalSection(&pContext->csMddAccess);
return dwRet;
}
// Disconnect the device from the USB bus.
DWORD
WINAPI
UfnMdd_Stop(
UFN_HANDLE hDevice
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
VERIFY_PCONTEXT();
VERIFY_RUNNING();
dwRet = DoStop(pContext);
EXIT:
FUNCTION_LEAVE_MSG();
return dwRet;
}
DWORD
DoDeregisterDevice(
PUFN_MDD_CONTEXT pContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet;
if (pContext->fRunning) {
// Must stop device before registering
DEBUGMSG(ZONE_ERROR, (_T("%s Device is still running\r\n"), pszFname));
dwRet = ERROR_BAD_ENVIRONMENT;
goto EXIT;
}
if (pContext->fRegistered == FALSE) {
// Must register before deregistering
DEBUGMSG(ZONE_ERROR, (_T("%s Device is not registered\r\n"), pszFname));
dwRet = ERROR_BAD_ENVIRONMENT;
goto EXIT;
}
pContext->PddInfo.pfnDeregisterDevice(pContext->PddInfo.pvPddContext);
FreeUsbStructs(pContext);
ResetPipeStatusTable(pContext);
pContext->fRegistered = FALSE;
dwRet = ERROR_SUCCESS;
EXIT:
FUNCTION_LEAVE_MSG();
return dwRet;
}
// Clears the registered descriptors.
DWORD
WINAPI
UfnMdd_DeregisterDevice(
UFN_HANDLE hDevice
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwRet;
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) hDevice;
BOOL fTookCS = FALSE;
VERIFY_PCONTEXT();
EnterCriticalSection(&pContext->csMddAccess);
fTookCS = TRUE;
dwRet = DoDeregisterDevice(pContext);
EXIT:
FUNCTION_LEAVE_MSG();
if (fTookCS) {
LeaveCriticalSection(&pContext->csMddAccess);
}
return dwRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -