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

📄 serial_dl.cpp

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // Update EP0 Request to send data, as this is a GET request.
    pRequest->eDir = EP0In;
    pRequest->pucData = pucData;
    pRequest->dwExpectedSize = pUdr->wLength;
    pRequest->dwActualSize = min(wLength, pUdr->wLength);
}

//------------------------------------------------------------------------------
//
//  Function:  HandleTransferComplete
//
//  Respond to UFN_MSG_TRANSFER_COMPLETE. Do some cleanup and change EP state.
//
void HandleTransferComplete(STransfer *pTransfer)
{
    if( pTransfer == &g_EP0Transfer )
    {
        g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
        g_EP0State = TS_IDLE;
    }
    else if( pTransfer == &g_EP1Transfer )
    {
        // Data received on BULK OUT endpoint
        if( g_EP1Transfer.dwUsbError != UFN_NO_ERROR )
        {
            OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated there was a transfer error on EP1!\r\n"));
            DEBUGCHK(0);
        }

        if(g_EP1State != TS_RECEIVING_PACKET)
        {
            OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated RECV complete before transfer issued! ep1st is 0x%X\r\n",g_EP1State));
            DEBUGCHK(0);
        }
        
        g_EP1State = TS_IDLE;
    }
    else if( pTransfer == &g_EP2Transfer )
    {
        if( g_EP2State == TS_SENDING_PACKET )
        {
            // Data sent on BULK IN endpoint
            if( g_EP2Transfer.cbTransferred != g_EP2Transfer.cbBuffer )
            {
                OALMSG(OAL_ERROR, (L"ERROR: Sent data does not match expected size!\r\n"));
                DEBUGCHK(0);
            }
            if( g_EP2Transfer.dwUsbError != UFN_NO_ERROR )
            {
                OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated there was a transfer error on EP2!\r\n"));
                DEBUGCHK(0);
            }

            if( (g_EP2Transfer.cbTransferred % EPMaxSize ) == 0 )
            {
                g_EP2Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
                g_EP2Transfer.pvBuffer = NULL;
                g_EP2Transfer.cbBuffer = 0;
                g_EP2Transfer.cbTransferred = 0;
                g_EP2Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR;
                g_EP2Transfer.pvPddData = NULL;
                g_EP2Transfer.pvPddTransferInfo = NULL;

                g_EP2State = TS_SENDING_PACKET_TERMINATOR;
                g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 2, &g_EP2Transfer );
             }
            else
            {
                 g_EP2State = TS_IDLE;
            }
        }
        else if ( g_EP2State == TS_SENDING_PACKET_TERMINATOR)
        {
            if( g_EP2Transfer.dwUsbError != UFN_NO_ERROR )
            {
                OALMSG(OAL_ERROR, (L"ERROR: PDD Indicated there was a transfer error on EP2 terminator!\r\n"));
                DEBUGCHK(0);
            }
            g_EP2State = TS_IDLE;
        }
        else
        {
            ASSERT(!"Endpoint 2 has entered an unsupported state!");
        }
    }
    else
    {
        ASSERT(!"PDD Signaled bogus transfer complete!");
    }
}

//------------------------------------------------------------------------------
//
//  Function:  HandleSetupPkt
//
//  Respond to SETUP packets as they come in from the PDD on EP0
//
static void HandleSetupPkt(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
    //At a minimum prepare to ACK the SETUP packet
    pRequest->eDir = EP0Setup;
    pRequest->pucData = NULL;
    pRequest->dwExpectedSize = 0;
    pRequest->dwActualSize = 0;
    pRequest->pfnNotification = NULL;
    pRequest->pvUser = NULL;

    switch( pUdr->bmRequestType )
    {
    case USB_REQUEST_DEVICE_TO_HOST:
    case USB_REQUEST_HOST_TO_DEVICE:
        switch( pUdr->bRequest )
        {
        case USB_REQUEST_GET_DESCRIPTOR:
            HandleGetDescriptor(pUdr, pRequest);
            break;

        case USB_REQUEST_SET_CONFIGURATION:
            g_DeviceState = DS_CONFIGURED;
            break;
        default:
            ASSERT(!"Only GET_DESC and SET_CONFIG supported!");
        }
        break;
    default:
        HandleClassRequest(pUdr, pRequest);
    }
}


//------------------------------------------------------------------------------
//
//  Function:  HandlePDDNotification
//
//  The USB FN PDD will call this function to notify it of various events (data sent/received, 
//  setup packet received, device addressed, reset, etc.
//
static BOOL WINAPI HandlePDDNotification (
    PVOID pvMddContext,
    DWORD dwMsg,
    DWORD dwParam
    )
{
    EP0_REQUEST Request;
    EP0_REQUEST *pRequest = &Request;

    switch( dwMsg )
    {
    case UFN_MSG_SETUP_PACKET:
        HandleSetupPkt( (USB_DEVICE_REQUEST*)(void*)dwParam, pRequest);

        pRequest->dwProcessed = 0;
        pRequest->fCompleted = FALSE;

        if( pRequest->eDir != EP0Setup )
        {
            g_EP0Transfer.pvBuffer = pRequest->pucData;
            g_EP0Transfer.cbBuffer = pRequest->dwActualSize;
            g_EP0Transfer.cbTransferred = 0;
            g_EP0Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR;
            g_EP0Transfer.pvPddData = NULL;
            g_EP0Transfer.pvPddTransferInfo = NULL;

            if( pRequest->eDir == EP0In )
            {
                OALMSG(OAL_FUNC, (L"Got SETUP IN packet\r\n"));
                g_EP0Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
                g_EP0State = TS_SENDING_MESSAGE;
                g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer);
            }
            else
            {
                OALMSG(OAL_FUNC, (L"Got SETUP OUT packet\r\n"));
                g_EP0Transfer.dwFlags = USB_REQUEST_HOST_TO_DEVICE;
                g_EP0State = TS_RECEIVING_MESSAGE;
                g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer);
            }        
        }
        else
        {
            g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
            g_EP0State = TS_IDLE;
        }
        break;

    case UFN_MSG_TRANSFER_COMPLETE:
        HandleTransferComplete( (STransfer*)(void*)dwParam);
        break;

    case UFN_MSG_BUS_EVENTS:
        switch( dwParam )
        {
        case UFN_DETACH:
            g_DeviceState = DS_DETACHED;
            break;
        case UFN_ATTACH:
            g_DeviceState = DS_ATTACHED;
            break;
        case UFN_RESET:
            g_DeviceState = DS_DEFAULT;
            // TODO: return to clean state?
            break;
        case UFN_SUSPEND:
            g_DeviceState = DS_SUSPENDED;
            break;
        case UFN_RESUME:
            g_DeviceState = DS_DEFAULT;
            break;
        default:
            ASSERT(!"Unexpected bus event!");
        }
        break;

    case UFN_MSG_BUS_SPEED:
        break;

    case UFN_MSG_SET_ADDRESS:
        if( dwParam ) g_DeviceState = DS_ADDRESSED;
        else g_DeviceState = DS_DEFAULT;
        break;

    default:
        ASSERT(!"Unexpected Msg in HandlePDDNotification!");
    }
    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  USBSerialInit
//
//  Lets send some data to the USB Bus.
//
BOOL USBSerialInit()
{
    if(g_USBSerialInitialized)
    {
        OALMSG(OAL_ERROR, (L"ERROR: USBSerialInit called again before USBSerialDeinit\r\n"));
        return FALSE;   
    }

    // Setup the MDD/PDD interface structures
    g_mddInterface.dwVersion = 1;
    g_mddInterface.pfnNotify = HandlePDDNotification;
    memset( &g_pddInterface, 0, sizeof(g_pddInterface) );
    g_pddInterface.dwVersion = 1;

    // Initialize our internal receive buffer markers
    g_RecvBufferHead = g_RecvBufferTail = 0;

    // Give the OEM an opportunity to setup clocks, GPIOs, etc:
    if( !InitializeHardware() )
    {
        OALMSG(OAL_ERROR, (L"InitializeHardware failed!"));
        return FALSE;
    }

    // Initialize USB Function block
    if( UfnPdd_Init( NULL, (PVOID)0xdeadbeef, &g_mddInterface, &g_pddInterface ) != ERROR_SUCCESS )
    {
        OALMSG(OAL_ERROR, (L"UfnPdd_Init failed!"));
        return FALSE;
    }

    // Negotiate with hardware by calling IsEndpointSupportable, IsConfigurationSupportable, etc.
    // Update descriptors to reflect negotiated endpoints.
    HandleUSBDeviceRegistration();

    // Setup complete, Attach device to USB bus
    g_pddInterface.pfnStart( g_pddInterface.pvPddContext );

    // Give time for host to recognize device
    // Sometimes we can hang without this delay
    msWait(1);

    // Respond to GET_DESCRIPTOR, SET_ADDRESS... until SET_CONFIGURATON
    while( g_DeviceState != DS_CONFIGURED )
    {
        InterruptThread( g_pddInterface.pvPddContext );
    }

    g_USBSerialInitialized = TRUE;
    return g_USBSerialInitialized;
}

//------------------------------------------------------------------------------
//
//  Function:  OEMSerialSendRaw
//
//  Lets send some data to the USB Bus.
//
BOOL OEMSerialSendRaw(LPBYTE pbFrame, USHORT cbFrame)
{
    if( !g_USBSerialInitialized)
    {
        OALMSG(OAL_ERROR, (L"ERROR: OEMSerialSendRaw called before USBSerialInit\r\n"));
        return g_USBSerialInitialized;
    }

    // Package the transfer information into a struct to pass to PDD
    g_EP2Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
    g_EP2Transfer.pvBuffer = pbFrame;
    g_EP2Transfer.cbBuffer = cbFrame;
    g_EP2Transfer.cbTransferred = 0;
    g_EP2Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; //possible values in usbfntypes.h
    g_EP2Transfer.pvPddData = NULL;
    g_EP2Transfer.pvPddTransferInfo = NULL;

    g_EP2State = TS_SENDING_PACKET;
    g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext,
        rgEndPoints[2].Descriptor.bEndpointAddress & 0x7F,
        &g_EP2Transfer);

    // Poll Interrupt thread until they call notification routine
    while( g_EP2State != TS_IDLE )
    {
        InterruptThread( g_pddInterface.pvPddContext );
    }

    return TRUE;
 }

//------------------------------------------------------------------------------
//
//  Function:  OEMSerialRecvRaw
//
//  Lets get some data from our internal buffer to return to caller. If we don't have enough data,
//  we'll wait until we get it from the USB bus.
//
BOOL OEMSerialRecvRaw(LPBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite)
{
    USHORT space;

    // Make sure OEMSerialRecvRaw is called before USBSerialInit
    if( !g_USBSerialInitialized)
    {
        OALMSG(OAL_ERROR, (L"ERROR: OEMSerialRecvRaw called before USBSerialInit\r\n"));
        return FALSE;
    }

    // Sanity check parameters
    if( *pcbFrame > RECV_BUFFER_SIZE - rgEndPoints[1].Descriptor.wMaxPacketSize + 1 )
    {
        OALMSG(OAL_ERROR, (L"ERROR: OEMSerialRecvRaw caller asking for 0x%X bytes\r\n",*pcbFrame));
        OALMSG(OAL_ERROR, (L"Must increase RECV_BUFFER_SIZE to accomodate request!\r\n"));
        OALMSG(OAL_ERROR, (L"Exiting OEMSerialRecvRaw....\r\n"));
        return FALSE;
    }

    // If our internal buffer cannot satisfy the receive request
    while( *pcbFrame > SPACE_IN_BUFFER(g_RecvBufferHead, g_RecvBufferTail) )
    {
        space = SPACE_IN_BUFFER(g_RecvBufferHead, g_RecvBufferTail);
    
        // Serial interface won't be able to wrap its pointer...account for this
        if( SPACE_UNTIL_WRAP(g_RecvBufferTail) < 
            rgEndPoints[1].Descriptor.wMaxPacketSize)
        {
            memmove( &g_RecvBuffer[0], &g_RecvBuffer[g_RecvBufferHead], space);
            g_RecvBufferHead = 0;
            g_RecvBufferTail = space;
        }

        // Package the transfer information into a struct to pass to PDD
        g_EP1Transfer.dwFlags = USB_REQUEST_HOST_TO_DEVICE;
        g_EP1Transfer.pvBuffer = &g_RecvBuffer[g_RecvBufferTail];
        g_EP1Transfer.cbBuffer = rgEndPoints[1].Descriptor.wMaxPacketSize;
        g_EP1Transfer.cbTransferred = 0;
        g_EP1Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; //possible values in usbfntypes.h
        g_EP1Transfer.pvPddData = NULL;
        g_EP1Transfer.pvPddTransferInfo = NULL;

        // Update state machine and kick off transfer
        g_EP1State = TS_RECEIVING_PACKET;
        g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext,
            rgEndPoints[1].Descriptor.bEndpointAddress & 0x7F,
            &g_EP1Transfer);
        while( g_EP1State != TS_IDLE )
        {
            InterruptThread( g_pddInterface.pvPddContext );
        }

        // Done, make sure amount transferred doesn't overflow caller's UCHAR
        if( (DWORD)(USHORT)g_EP1Transfer.cbTransferred != g_EP1Transfer.cbTransferred )
        {
            ASSERT(!"Amount of transferred data in DWORD too large for EBOOTs UCHAR!");
        }

        // Advance buffer's tail
        g_RecvBufferTail = g_RecvBufferTail + (USHORT)g_EP1Transfer.cbTransferred;
        if( g_RecvBufferTail >= RECV_BUFFER_SIZE )
        {
            ASSERT(!"Serial Wrapper Circular Buffer Overflow error!!!");
        }
    }

    // Now, we definately have enough space to work with
    ASSERT(*pcbFrame <= SPACE_IN_BUFFER(g_RecvBufferHead, g_RecvBufferTail) );

    // Lets give the caller what he wants, advance our buffer's head
    memcpy(pbFrame, &g_RecvBuffer[g_RecvBufferHead], *pcbFrame );
    g_RecvBufferHead += *pcbFrame;

    return TRUE;
}




⌨️ 快捷键说明

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