⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 enum.cpp

📁 It permits simultaneous use of multiple USB Serial protocols.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//

#include "ufnmdd.h"

#define GET_DESCRIPTOR_TYPE(x)          HIBYTE(x)
#define GET_DESCRIPTOR_INDEX(x)         LOBYTE(x)

#define USB_REQUEST_RECIPIENT_MASK      0x1F
#define GET_REQUESET_RECIPIENT(x)       ((x) & USB_REQUEST_RECIPIENT_MASK)


enum CONTROL_RESPONSE {
    CR_SUCCESS = 0,
    CR_SUCCESS_SEND_CONTROL_HANDSHAKE, // Use if no data stage
    CR_STALL_DEFAULT_PIPE,
    CR_UNHANDLED_REQUEST,
};

#ifdef DEBUG

static const LPCTSTR g_rgpszDeviceStates[] = {
    _T("detached"),
    _T("attached"),
    _T("powered"),
    _T("default"),
    _T("addressed"), 
    _T("configured"),
    _T("suspended"), 
};

// Get a textual name of a device state.
LPCTSTR
GetDeviceStateName(
    DEVICE_STATE ds
    )
{
    DEBUGCHK(ds < dim(g_rgpszDeviceStates));
    LPCTSTR psz = g_rgpszDeviceStates[ds];
    return psz;
}

#endif


// Return the configuration tree structure for the given speed.
static
PUFN_CONFIGURATION
GetConfig(
    PUFN_MDD_CONTEXT pContext,
    UFN_BUS_SPEED    Speed
    )
{
    DEBUGCHK(pContext);
    DEBUGCHK( (Speed == BS_FULL_SPEED) || (Speed == BS_HIGH_SPEED) );
    PUFN_CONFIGURATION pConfig;

    if (Speed == BS_HIGH_SPEED) {
        pConfig = &pContext->HighSpeedConfig;
    }
    else {
        pConfig = &pContext->FullSpeedConfig;
    }

    return pConfig;
}


DWORD
static
WINAPI 
EnumTransferComplete(
    PVOID pvNotifyParameter
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PUFN_MDD_CONTEXT pContext = (PUFN_MDD_CONTEXT) pvNotifyParameter;    

    UFN_TRANSFER hTransfer = pContext->hEnumTransfer;
	pContext->hEnumTransfer = NULL;
    DWORD dwUsbError;
    DWORD cbTransferred;

    PREFAST_DEBUGCHK(hTransfer);

    DWORD dwErr = UfnMdd_GetTransferStatus(pContext, hTransfer, &cbTransferred, 
        &dwUsbError);
    DEBUGCHK(dwErr == ERROR_SUCCESS);

    dwErr = UfnMdd_CloseTransfer(pContext, hTransfer);
    DEBUGCHK(dwErr == ERROR_SUCCESS);

    DEBUGMSG(ZONE_USB_EVENTS, (_T("%s %u bytes written\r\n"), pszFname, 
        cbTransferred));

    if (dwUsbError == UFN_NO_ERROR) {
        PCPipe pPipe = &pContext->pPipes[0];
        pPipe->SendControlStatusHandshake();
    }

    FUNCTION_LEAVE_MSG();
    
    return ERROR_SUCCESS;
}


// Setup for a transfer.
static
VOID
SetupTx(
    PUFN_MDD_CONTEXT pContext,
    PVOID  pvBuffer,
    DWORD  cbBuffer,
    DWORD  cbRequested
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    DEBUGCHK(pvBuffer);

    DWORD cbToSend = min(cbRequested, cbBuffer);
    
    DEBUGMSG(ZONE_SEND, (_T("%s Asked to send %u of %u bytes. Sending %u bytes.\r\n"),
        pszFname, cbRequested, cbBuffer, cbToSend));

    PCPipe pPipeEndpoint0 = &pContext->pPipes[0];
    
    DEBUGCHK(pContext->hEnumTransfer == NULL);
    DWORD dwErr = UfnMdd_IssueTransfer(pContext, pPipeEndpoint0, 
        &EnumTransferComplete, pContext, USB_IN_TRANSFER, cbToSend,
        pvBuffer, 0, NULL, &pContext->hEnumTransfer);

    FUNCTION_LEAVE_MSG();
}


// Handle a Get Descriptor request.
static
CONTROL_RESPONSE
ProcessGetDescriptor(
    PUFN_MDD_CONTEXT pContext,
    USB_DEVICE_REQUEST udr,
    DWORD dwMsg
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    ValidateContext(pContext);
    DEBUGCHK( (pContext->Speed == BS_HIGH_SPEED) || 
        (pContext->Speed == BS_FULL_SPEED) );

    CONTROL_RESPONSE response = CR_SUCCESS;

    if (dwMsg == UFN_MSG_PREPROCESSED_SETUP_PACKET) {
        // Nothing to do.
        goto EXIT;
    }

    DWORD dwType = GET_DESCRIPTOR_TYPE(udr.wValue);
    DWORD dwIndex = GET_DESCRIPTOR_INDEX(udr.wValue);

    PVOID pvBuffer = NULL;
    DWORD cbBuffer;

    if ( (dwType != USB_STRING_DESCRIPTOR_TYPE) && (udr.wIndex != 0) ) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Invalid wIndex value %u\r\n"), 
            pszFname, udr.wIndex));
        response = CR_STALL_DEFAULT_PIPE;
    }
    else if ( (dwType == USB_DEVICE_DESCRIPTOR_TYPE) && (dwIndex == 0) ) {
        DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Get device descriptor request.\r\n"),
            pszFname));

        if (pContext->Speed == BS_HIGH_SPEED) {
            pvBuffer = &pContext->HighSpeedDeviceDesc;
        }
        else {
            pvBuffer = &pContext->FullSpeedDeviceDesc;
        }
        
        cbBuffer = sizeof(USB_DEVICE_DESCRIPTOR);
    }
    else if ( (dwType == USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE) && (dwIndex == 0) ) {
        DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Get device qualifier descriptor request.\r\n"),
            pszFname));
        PUSB_DEVICE_DESCRIPTOR pDeviceDesc = NULL;

        if (pContext->Speed == BS_HIGH_SPEED) {
            pDeviceDesc = &pContext->FullSpeedDeviceDesc;
        }
        else {            
            if (PddSupportsHighSpeed(pContext)) {
                pDeviceDesc = &pContext->HighSpeedDeviceDesc;
            }
        }

        if (pDeviceDesc) {
            cbBuffer = sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR);
            memcpy(&pContext->DeviceQualifierDescToSend, pDeviceDesc, cbBuffer);

            // Copy over the values that do match
            pContext->DeviceQualifierDescToSend.bLength = 
                sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR);
            pContext->DeviceQualifierDescToSend.bDescriptorType = (BYTE) dwType;
            pContext->DeviceQualifierDescToSend.bNumConfigurations = 
                pDeviceDesc->bNumConfigurations;
            pContext->DeviceQualifierDescToSend.bReserved = 0;

            pvBuffer = &pContext->DeviceQualifierDescToSend;
        }
        else {
            // We are connected at full speed and there is no support 
            // for high speed.
            response = CR_STALL_DEFAULT_PIPE;
        }
    }
    else if ( (dwType == USB_CONFIGURATION_DESCRIPTOR_TYPE) || 
              (dwType == USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE) ||
              (dwType == USB_OTG_CONFIGURATION_DESCRIPTOR_TYPE)) {
        if (dwIndex == 0) {
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Get dwType=%d configuration descriptor request.\r\n"),
                pszFname, dwType  ) );
            
            PUSB_CONFIGURATION_DESCRIPTOR pConfigDesc;

            if (dwType == USB_CONFIGURATION_DESCRIPTOR_TYPE) {
                if (pContext->Speed == BS_HIGH_SPEED) {
                    pConfigDesc = pContext->pHighSpeedConfigDesc;
                }
                else {
                    pConfigDesc = pContext->pFullSpeedConfigDesc;
                }
            }
            else if ( (dwType == USB_OTG_CONFIGURATION_DESCRIPTOR_TYPE)) {
                // Copy over the values that do match
                pContext->USBOTGDescToSend.bLength = sizeof (USB_OTG_DESCRIPTOR);
                pContext->USBOTGDescToSend.bDescriptorType = USB_OTG_CONFIGURATION_DESCRIPTOR_TYPE;
                pContext->USBOTGDescToSend.bmAttributes = ((pContext->uOTGCapabilityBits & USBOTG_DEVICE_ENABLE)!=0?3:0);
                pvBuffer = &pContext->USBOTGDescToSend;
            }
            else {
                DEBUGCHK(dwType == USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE);
                DEBUGCHK(PddSupportsHighSpeed(pContext));
                
                if (pContext->Speed == BS_HIGH_SPEED) {
                    pConfigDesc = pContext->pFullSpeedConfigDesc;
                }
                else {
                    pConfigDesc = pContext->pHighSpeedConfigDesc;
                }
            }

            pConfigDesc->bDescriptorType = (BYTE) dwType;
            pvBuffer = pConfigDesc;
            cbBuffer = pConfigDesc->wTotalLength;
        }
        else {
            DEBUGMSG(ZONE_ERROR, (_T("%s Invalid configuration number %u\r\n"), 
                pszFname, dwIndex));
            response = CR_STALL_DEFAULT_PIPE;
        }
    }
    else if (dwType == USB_STRING_DESCRIPTOR_TYPE) {
        WORD wLang = udr.wIndex;
        DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Get string descriptor request. Lang 0x%04x Idx %u\r\n"),
            pszFname, wLang, dwIndex));

        if (pContext->cStringSets) {
            PUSB_STRING_DESCRIPTOR pStringDesc = (PUSB_STRING_DESCRIPTOR) 
                pContext->rgbStringDesc;
            pStringDesc->bDescriptorType = USB_STRING_DESCRIPTOR_TYPE;
            DWORD cbData;

            if (dwIndex == 0) {
                DEBUGCHK(pContext->cStringSets <= MAX_STRING_DESC_WCHARS);

                DWORD dwLangId;
                for (dwLangId = 0; dwLangId < pContext->cStringSets; ++dwLangId) {
                    pStringDesc->bString[dwLangId] = 
                        pContext->pStringSets[dwLangId].wLangId;
                }

                cbData = pContext->cStringSets * sizeof(WCHAR);
            }
            else {
                DWORD dwLangId;
                PUFN_STRING_SET pStringSet;
                for (dwLangId = 0; dwLangId < pContext->cStringSets; ++dwLangId) {
                    pStringSet = &pContext->pStringSets[dwLangId];
                    if (pStringSet->wLangId == wLang) {
                        break;
                    }
                }

                if (dwLangId == pContext->cStringSets) {
                    // Perhaps the client wishes to process string requests.
                    DEBUGMSG(ZONE_WARNING, (_T("%s Invalid language id 0x%04x\r\n"), 
                        pszFname, wLang));
                    response = CR_UNHANDLED_REQUEST;
                }
                else {
                    --dwIndex;
                    
                    if (dwIndex < pStringSet->cStrings) {
                        LPCWSTR pszString = pStringSet->ppszStrings[dwIndex];
                        DWORD cchString = wcslen(pszString);
                        DEBUGCHK(cchString <= MAX_STRING_DESC_WCHARS);
                        // Do not copy NULL terminator.
                        wcsncpy(pStringDesc->bString, pszString, cchString);
                        cbData = cchString * sizeof(WCHAR);
                    }
                    else {
                        // Perhaps the client wishes to process string requests.
                        DEBUGMSG(ZONE_WARNING, (_T("%s Invalid string index %u\r\n"), 
                            pszFname, dwIndex));
                        response = CR_UNHANDLED_REQUEST;
                    }
                }
            }

            if (response == CR_SUCCESS) {
                pStringDesc->bLength = (UCHAR) (sizeof(USB_STRING_DESCRIPTOR) - 
                    sizeof(pStringDesc->bString) + cbData);
                pvBuffer = pStringDesc;
                cbBuffer = pStringDesc->bLength;
            }
        }
        else {
            // Perhaps the client wishes to process string requests.
            DEBUGMSG(ZONE_WARNING, (_T("%s Request for strings, but MDD has none. Index %u\r\n"), 
                pszFname, dwIndex));
            response = CR_UNHANDLED_REQUEST;
        }
    }
    else {
        DEBUGMSG(ZONE_ERROR, (_T("%s Invalid GetDescriptor request\r\n"),
            pszFname));
        response = CR_STALL_DEFAULT_PIPE;
    }

    if (pvBuffer) {
        DEBUGCHK(response == CR_SUCCESS);
        SetupTx(pContext, (PBYTE) pvBuffer, cbBuffer, udr.wLength);
    }

EXIT:
    FUNCTION_LEAVE_MSG();

    return response;
}


// Handle a Get Configuration request.
static
CONTROL_RESPONSE
ProcessGetConfiguration(
    PUFN_MDD_CONTEXT pContext,
    USB_DEVICE_REQUEST udr,
    DWORD dwMsg
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    ValidateContext(pContext);

    if (dwMsg == UFN_MSG_PREPROCESSED_SETUP_PACKET) {
        // Nothing to do.
        goto EXIT;
    }

    const DWORD dwLength = 1;
    DEBUGCHK(dim(pContext->rgbBuffer) >= dwLength);

    DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Get configuration.\r\n"), pszFname)); 

    PUFN_CONFIGURATION pConfig = GetConfig(pContext, pContext->Speed);
    BYTE bConfigurationValue = pConfig->Descriptor.bConfigurationValue;
    
    DEBUGCHK( 
        ( (pContext->deviceState == DS_ADDRESSED)  && (pContext->dwConfiguration == 0) ) ||
        ( (pContext->deviceState == DS_CONFIGURED) && (pContext->dwConfiguration == bConfigurationValue) )
        );
    
    pContext->rgbBuffer[0] = (BYTE) pContext->dwConfiguration;
    SetupTx(pContext, pContext->rgbBuffer, dwLength, udr.wLength);

    FUNCTION_LEAVE_MSG();

EXIT:
    return CR_SUCCESS;
}


// Handle a Get Interface request.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -