📄 enum.cpp
字号:
ValidateContext(pContext);
CONTROL_RESPONSE (*pfnProcess)(PUFN_MDD_CONTEXT, USB_DEVICE_REQUEST, DWORD) = NULL;
// Process device-to-host requests
if ( udr.bmRequestType ==
(USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE) ) {
// Process device requests
switch (udr.bRequest) {
case USB_REQUEST_GET_DESCRIPTOR:
pfnProcess = &ProcessGetDescriptor;
break;
case USB_REQUEST_GET_CONFIGURATION:
pfnProcess = &ProcessGetConfiguration;
break;
case USB_REQUEST_GET_STATUS:
pfnProcess = &ProcessGetStatus;
break;
}
}
else if ( udr.bmRequestType ==
(USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_STANDARD | USB_REQUEST_FOR_INTERFACE) ) {
// Process interface requests
switch (udr.bRequest) {
case USB_REQUEST_GET_INTERFACE:
pfnProcess = &ProcessGetInterface;
break;
case USB_REQUEST_GET_STATUS:
pfnProcess = &ProcessGetStatus;
break;
}
}
else if ( udr.bmRequestType ==
(USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_STANDARD | USB_REQUEST_FOR_ENDPOINT) ) {
// Process interface requests
switch (udr.bRequest) {
case USB_REQUEST_GET_STATUS:
pfnProcess = &ProcessGetStatus;
break;
}
}
// Process host-to-device requests
else if ( udr.bmRequestType ==
(USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE) ) {
switch (udr.bRequest) {
case USB_REQUEST_SET_ADDRESS:
pfnProcess = &ProcessSetAddress;
break;
case USB_REQUEST_SET_CONFIGURATION:
pfnProcess = &ProcessSetConfiguration;
break;
case USB_REQUEST_CLEAR_FEATURE:
pfnProcess = &ProcessClearFeature;
break;
case USB_REQUEST_SET_FEATURE:
pfnProcess = &ProcessSetFeature;
break;
}
}
else if ( udr.bmRequestType ==
(USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_INTERFACE) ) {
switch (udr.bRequest) {
case USB_REQUEST_SET_INTERFACE:
pfnProcess = &ProcessSetInterface;
break;
}
}
else if ( udr.bmRequestType ==
(USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_ENDPOINT) ) {
switch (udr.bRequest) {
case USB_REQUEST_CLEAR_FEATURE:
pfnProcess = &ProcessClearFeature;
break;
case USB_REQUEST_SET_FEATURE:
pfnProcess = &ProcessSetFeature;
break;
}
}
CONTROL_RESPONSE response;
if (pfnProcess) {
response = pfnProcess(pContext, udr, dwMsg);
}
else {
response = CR_UNHANDLED_REQUEST;
}
FUNCTION_LEAVE_MSG();
return response;
}
static
VOID
CloseAllPipesExceptEndpointZero(
PUFN_MDD_CONTEXT pContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
ValidateContext(pContext);
PREFAST_DEBUGCHK(pContext->pPipes);
// Don't close endpoint 0.
for (DWORD dwPipe = 1; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
PCPipe pPipe = &pContext->pPipes[dwPipe];
if (pPipe->IsOpen()) {
pPipe->Close();
}
}
FUNCTION_LEAVE_MSG();
}
// Performs the check to see if we are ready for a notification.
static
inline
BOOL
IgnoreNotificationCheck(
PUFN_MDD_CONTEXT pContext
)
{
return (!pContext->pUfnBus->IsClientActive() || pContext->fClientIsBeingAddedOrRemoved);
}
// Ignore this notification because we are not ready for it?
static
BOOL
IgnoreNotification(
PUFN_MDD_CONTEXT pContext,
DWORD dwMsg,
DWORD dwParam
)
{
BOOL fIgnore = IgnoreNotificationCheck(pContext);
if (fIgnore) {
// We may not be ready to receive notifications--perhaps we
// are in the process of loading the client driver. Verify
// that we are ready and then check the other flags again.
WaitForSingleObject(pContext->hevReadyForNotifications, READY_FOR_NOTIFICATIONS_TIMEOUT);
fIgnore = IgnoreNotificationCheck(pContext);
}
if (fIgnore == FALSE) {
// Ignore notifications when detached
if ( (pContext->deviceState == DS_DETACHED) &&
(dwMsg != UFN_MSG_BUS_EVENTS || dwParam != UFN_ATTACH) ) {
fIgnore = TRUE;
}
}
return fIgnore;
}
// Notification routine for the device.
BOOL
WINAPI
UfnMdd_Notify(
PVOID pvNotifyParameter,
DWORD dwMsg,
DWORD dwParam
)
{
SETFNAME();
PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) pvNotifyParameter;
ValidateContext(pContext);
FUNCTION_ENTER_MSG();
BOOL fRet = FALSE;
CONTROL_RESPONSE response = CR_SUCCESS;
BOOL fSendNotificationToClient = TRUE;
BOOL fEnteredCs = FALSE;
if (dwMsg == UFN_MSG_TRANSFER_COMPLETE) {
PSTransfer pPddTransfer = (PSTransfer) dwParam;
PCUfnMddTransfer pTransfer = CUfnMddTransfer::ConvertFromPddTransfer(pPddTransfer);
DWORD dwErr = CUfnMddTransfer::ReferenceTransferHandle(pTransfer);
if (dwErr == ERROR_SUCCESS) {
DEBUGCHK(pTransfer->IsInPdd());
pTransfer->LeavingPdd();
PCPipe pPipe = pTransfer->GetPipe();
dwErr = pPipe->TransferComplete(pTransfer, TRUE);
pTransfer->Release();
fRet = TRUE;
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s PDD passed a bad transfer\r\n"),
pszFname));
}
goto EXIT;
}
if (IgnoreNotification(pContext, dwMsg, dwParam)) {
// Are we receiving a notification before the client is fully initialized?
// If so try adding a sleep to the PDD's IST before enabling interrupts.
RETAILMSG(1, (_T("%s Ignoring notification 0x%08x - 0x%08x from PDD\r\n"),
pszFname, dwMsg, dwParam));
goto EXIT;
}
EnterCriticalSection(&pContext->csMddAccess);
fEnteredCs = TRUE;
PCPipe pPipeZero = &pContext->pPipes[0];
switch(dwMsg) {
case UFN_MSG_BUS_EVENTS: {
DEVICE_STATE dsNew;
BOOL fChangeState = TRUE;
switch (dwParam) {
case UFN_DETACH:
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Detached\r\n"), pszFname));
if (pContext->deviceState == DS_DETACHED) {
DEBUGMSG(ZONE_WARNING, (_T("%s Received detach when already detached!\r\n"),
pszFname));
fChangeState = FALSE;
}
else {
dsNew = DS_DETACHED;
}
// Free resources associated with free transfers
pContext->pFreeTransferList->Compact();
break;
case UFN_ATTACH:
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Attached\r\n"), pszFname));
if (pContext->deviceState == DS_ATTACHED) {
DEBUGMSG(ZONE_WARNING, (_T("%s Received attach when already attached!\r\n"),
pszFname));
fChangeState = FALSE;
}
else {
dsNew = DS_ATTACHED;
pContext->Speed = BS_UNKNOWN_SPEED;
pContext->fRemoteWakeupEnabled = FALSE;
}
break;
case UFN_RESET:
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Root port reset\r\n"), pszFname));
if (pContext->deviceState == DS_DETACHED) {
DEBUGMSG(ZONE_WARNING, (_T("%s Received reset when detached!\r\n"),
pszFname));
fChangeState = FALSE;
}
else {
dsNew = DS_DEFAULT;
pContext->dwConfiguration = 0;
pContext->fRemoteWakeupEnabled = FALSE;
}
if (pContext->hParentBusHandle != NULL ) {
BusChildIoControl(pContext->hParentBusHandle,IOCTL_BUS_USBOTG_HNP_DISABLE,NULL,0);
}
break;
case UFN_SUSPEND:
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Suspended\r\n"), pszFname));
DEBUGCHK(pContext->deviceState != DS_DETACHED);
pContext->deviceStatePriorToSuspend = pContext->deviceState;
dsNew = DS_SUSPENDED;
// Need to call bus driver to indicate bus suspend.
if (pContext->hParentBusHandle != NULL ) {
BusChildIoControl(pContext->hParentBusHandle,IOCTL_BUS_USBOTG_SUSPEND,NULL,0);
}
break;
case UFN_RESUME:
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Resumed\r\n"), pszFname));
DEBUGCHK(pContext->deviceState != DS_DETACHED);
dsNew = pContext->deviceStatePriorToSuspend;
// Need to call bus driver to indicate bus suspend.
if (pContext->hParentBusHandle != NULL ) {
BusChildIoControl(pContext->hParentBusHandle,IOCTL_BUS_USBOTG_RESUME,NULL,0);
}
break;
default:
DEBUGCHK(FALSE); // What message is this?
dsNew = pContext->deviceState;
}
if (fChangeState) {
ChangeDeviceState(pContext, dsNew);
CloseAllPipesExceptEndpointZero(pContext);
pPipeZero->AbortAllTransfers();
}
else {
fSendNotificationToClient = FALSE;
}
break;
}
case UFN_MSG_BUS_SPEED:
DEBUGCHK( (dwParam == BS_HIGH_SPEED) || (dwParam == BS_FULL_SPEED) );
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Attached to %s speed bus.\r\n"),
pszFname, (dwParam == BS_HIGH_SPEED ? _T("high") : _T("full") )));
DEBUGCHK(pContext->deviceState != DS_DETACHED);
DEBUGCHK((pContext->PddInfo.dwCapabilities & dwParam) != 0);
pContext->Speed = (UFN_BUS_SPEED) dwParam;
break;
case UFN_MSG_SETUP_PACKET:
case UFN_MSG_PREPROCESSED_SETUP_PACKET: {
PUSB_DEVICE_REQUEST pUdr = (PUSB_DEVICE_REQUEST) dwParam;
PREFAST_DEBUGCHK(pUdr);
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Received %s setup packet: %02x %02x %04x %04x %04x\r\n"),
pszFname, (dwMsg == UFN_MSG_SETUP_PACKET ? _T("") : _T("preprocessed")),
pUdr->bmRequestType, pUdr->bRequest, pUdr->wValue,
pUdr->wIndex, pUdr->wLength));
DEBUGCHK(pContext->deviceState != DS_DETACHED);
response = ProcessRequest(pContext, *pUdr, dwMsg);
if (dwMsg == UFN_MSG_SETUP_PACKET) {
if (response == CR_UNHANDLED_REQUEST) {
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Unhandled setup packet. Passing it to client\r\n"),
pszFname));
}
else {
dwMsg = UFN_MSG_PREPROCESSED_SETUP_PACKET;
}
}
break;
}
case UFN_MSG_SET_ADDRESS: {
// Some controllers automatically handle set address so they must
// tell us when the device has been addressed.
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Set address (%u).\r\n"),
pszFname, dwParam));
DEBUGCHK(pContext->deviceState != DS_DETACHED);
DEBUGCHK(pContext->deviceState != DS_CONFIGURED);
DEVICE_STATE ds;
if (dwParam == 0) {
ds = DS_DEFAULT;
}
else {
ds = DS_ADDRESSED;
}
ChangeDeviceState(pContext, ds);
break;
}
case UFN_MSG_CONFIGURED: {
// Some controllers automatically handle set address so they must
// tell us when the device has been addressed.
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Set configuration (%u).\r\n"),
pszFname, dwParam));
DEBUGCHK(pContext->deviceState != DS_DETACHED);
if (dwParam == 0) {
ChangeDeviceState(pContext, DS_ADDRESSED);
}
else {
DEBUGCHK(pContext->deviceState == DS_ADDRESSED);
ChangeDeviceState(pContext, DS_CONFIGURED);
}
break;
}
default:
DEBUGCHK(FALSE); // What is this message?
}
if (fSendNotificationToClient) {
fRet = SendDeviceNotification(pContext->lpDeviceNotify,
pContext->pvDeviceNotifyParameter, dwMsg, dwParam);
}
if (response == CR_STALL_DEFAULT_PIPE) {
pPipeZero->Stall();
pPipeZero->SendControlStatusHandshake();
}
else if (response == CR_SUCCESS_SEND_CONTROL_HANDSHAKE) {
pPipeZero->SendControlStatusHandshake();
}
EXIT:
FUNCTION_LEAVE_MSG();
if (fEnteredCs) {
LeaveCriticalSection(&pContext->csMddAccess);
}
return fRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -