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

📄 ncdevice.c

📁 CE下 NET2778 NDIS Drivers, 在每个平台上都可以使用
💻 C
📖 第 1 页 / 共 5 页
字号:
                NETCHIP_BASEADDRESS[EP_DATA].NcReg = *(pTxBuf++);
                NETCHIP_WRITE(LOCCTL, LocCtl);
            }
#endif
            // Post-validate partially-filled (or even empty) buffer:
            //  - Final bytes of the USB transfer have been written into the NET2272
            //    buffers. Validate the endpoint to allow the endpoint logic to send 
            //    a short (or zero length) packet
            //  - ZLP tip: If the transfer is an exact packet multiple, firmware adds
            //    a ZLP. If the host does not take the ZLP (e.g. wLength is an exact
            //    packet multiple, AND the device is to return exactly wLength bytes)
            //    the extraneous ZLP gets discarded by endpoint logic on the next Setup Request. 
            NETCHIP_WRITE(EP_TRANSFER2, 0);
            NETCHIP_WRITE(EP_TRANSFER1, 0);
            NETCHIP_WRITE(EP_TRANSFER0, 0);

            // Data phase transfer completed successfully
            Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
            HISTO(DEFAULT_HISTORY, "TCmp", NETCHIP_READ(EP_CFG), NETCHIP_READ(EP_STAT0), 0);
            break;
        }
    }

    NC_LED2(FALSE);     // Turn RDK daughter board LED OFF
    HISTO(DEFAULT_HISTORY, ")TxP", Endpoint->Priv.pPkt - (PBYTE)Endpoint->Transfer->TransferBuffer, NETCHIP_READ(EP_STAT0), Endpoint->Priv.BytesRemaining);
}

///////////////////////////////////////////////////////////////////////////////
STATIC void
EpZero_StatusPhase(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Status phase is the last phase of a Control Transfer (See USB 2.0 8.5.3)
    //  - Allow the status phase to complete
    //  - Lowest priority: Setup and data phase handlers must complete before this section runs!
    PNC_TRANSFER_OBJECT Transfer = Endpoint->Transfer;

    NETCHIP_WRITE(PAGESEL, EP0);
    HISTO(DEFAULT_HISTORY, "StPh", NETCHIP_READ(EP_CFG), NETCHIP_READ(EP_STAT0), NETCHIP_READ(IRQSTAT1));

    // Allow the status phase of the control transfer to complete
    //  - Control Status Phase Handshake was set by the chip when the setup packet 
    //    arrived. While set, the chip automatically NAKs the host's Status Phase tokens.
    //  - Once Control Status Phase Handshake is cleared, the host and NET2272 
    //    will quickly handshake to complete the status phase
    //  - Tip: Endpoint Zero changes its direction to match the Status Phase
    //    as soon as the host *starts* issuing Status Phase tokens! After a data
    //    phase completes, firmware must be careful with endpoint registers, as
    //    the endpoint direction could change at any time!
    NETCHIP_WRITE(EP_RSPCLR, 1<<CONTROL_STATUS_PHASE_HANDSHAKE);

    // Prevent Control Status Interrupt (Status Phase) from interrupting again:
    //  - On the next Setup Request (Setup Phase) interrupt, firmware should clear 
    //    Control Status Interrupt and enable its interrupt
    NETCHIP_WRITE(IRQENB1, NETCHIP_READ(IRQENB1) & ~(1<<CONTROL_STATUS_INTERRUPT_ENABLE));

    if (WLENGTH != 0)
    {   // Host's request included a data phase
        //  - Client should have started a data phase (in its setup request handler)
        //  - Data phase may (or may not!) have completed 
        //  - Clean up and call client completion handler
        NETCHIP_WRITE(EP_IRQENB, 0);
        Endpoint->BytesTransferred = Endpoint->Priv.pPkt - (PBYTE)Transfer->TransferBuffer;

        NC_STATISTIC(LogicalEndpoints[0].Priv.TotalBytesTransferred += Endpoint->BytesTransferred;)
        NC_STATISTIC(LogicalEndpoints[0].Priv.TotalTransfers++;)
        _NC_DISPLAY_MEMORY(VOLUME_MAXIMUM, Endpoint->Transfer->TransferBuffer, Endpoint->BytesTransferred, WORDSIZE_BYTE);

        if (Endpoint->CompletionStatus == NCSTATUS_PENDING)
        {   // A data phase transfer was started, but the host ended the data phase
            // before the data phase could complete
            //  - Data phase has not completed normally. Post error code for client
            NCPRINTF(VOLUME_MINIMUM, ("EpZero_StatusPhase(): Completing Data Phase early!\n")); 
            HISTO(DEFAULT_HISTORY, "StE!", NETCHIP_READ(EP_CFG), NETCHIP_READ(EP_STAT0), NETCHIP_READ(IRQSTAT1));
            Endpoint->CompletionStatus = NCSTATUS_UNSUCCESSFUL;
        }

        // Call client's transfer completion handler
        //  - Client should return from this call as quickly as possible
        ASSERT(Transfer->ClientCompletionHandler != NULL);
        Transfer->ClientCompletionHandler(Endpoint);
    }

    //Assert: There should not be any Endpoint Zero transfers pending:
    // - Client must NOT start an Endpont Zero transfer from its completion handler. Client 
    //   can only start an Endpoint Zero transfer from its Device Request Handler
    ASSERT(Endpoint->CompletionStatus != NCSTATUS_PENDING);

    // Restore client's transfer object
    Endpoint->Transfer = ClientTransferZero;
}

///////////////////////////////////////////////////////////////////////////////
STATIC void
EpZero_DataPhase(
    PNC_ENDPOINT_OBJECT Endpoint
    )
{   // Start or continue the data phase (Control Read or Write) of a control transfer
    //  - If data phase completes (or there is no data phase) allow the status phase
    //    to complete
    //  - See USB 2.0: 8.5.3
    // Tips and considerations: Control transfers have subtle issues. NetChip firmware
    // is carefully crafted to ensure that these issues won't create problems regardless
    // of the platform the code is ported to. However a few of the issues are discussed 
    // here for those wishing to investigate NetChip methods:
    //  - The host may move to the Status Stage early, terminating a control transfer
    //    before all bytes of the data phase have been transferred. Firmware must
    //    be able to recognize this situation respond correctly, predictably and reliably.
    //  - Firmware must be immune to sudden changes in Endpoint Direction. When the host 
    //    moves to the Status Stage, the NET2272 will soon switch its direction to match. For 
    //    instance, if the Data Stage is OUT (Control Write) the host will likely 
    //    issue Status Stage IN tokens soon after the final data phase OUT packet 
    //    is ACK'd. When firmware eventually reads the final data phase byte from the 
    //    endpoint, the endpoint logic will switch from being an OUT endpoint to IN 
    //    endpoint. At that moment, various Endpoint Zero registers will switch as appropriate 
    //    for an IN endpoint; firmware must act correctly, predictably and reliably.
    //  - Hide Status Phase OFF: 'Stale' Packet Received and Packet Transmitted 
    //    bits may be left over from the status phase of a previous control transfer. These
    //    stale bits must not cause problems. Consider, for instance, a Control Read 
    //    followed closely by a Control Write: The status phase of the Control Read 
    //    will set Packet Received; the data phase of the Control Write will *also* set
    //    Packet Received! It may be difficult for firmware to distinguish the 
    //    difference. If Hide Status Phase is OFF, control transfer firmware must 
    //    robustly handle such possibilities.
    NCDEBUG(PNC_TRANSFER_OBJECT Transfer = Endpoint->Transfer;)

    NETCHIP_WRITE(PAGESEL, EP0);
    HISTO(DEFAULT_HISTORY, "DaPh", BMREQUESTTYPE, NETCHIP_READ(EP_STAT0), WLENGTH);
    if (Endpoint->CompletionStatus == NCSTATUS_PENDING)
    {   // Control transfer includes an uncompleted data phase
        //  - Transfer as much data-phase data as possible now
        if (BMREQUESTTYPE & DEVICE_TO_HOST)
        {   // Control Read (USB IN)
            //  - Assert: Transfer size restriction: The client's transfer must be
            //    no larger than the host's requested size:
            ASSERT(Endpoint->Priv.BytesRemaining <= WLENGTH);
            EpZero_TxPackets(Endpoint);
        }
        else if (WLENGTH != 0)
        {   // Control Write (USB OUT), with some number of bytes
            // Assert: Transfer size restriction: 
            //  - The client must provide at least enough room for the 
            //    host's requested size, but also, the client should not
            //    specify a transfer size larger than the host's request
            //  - Problems with endpoint switching (Endpoint Zero switching 
            //    to an IN endpoint on status phase) can otherwise arise
            ASSERT(WLENGTH == Transfer->TransferSize);
            EpZero_RxPackets(Endpoint);
        }
        else
        {   // Zero-length Control Write
            //  - No data to transfer!
            Endpoint->CompletionStatus = NCSTATUS_SUCCESS;
        }
    }

    if (Endpoint->CompletionStatus != NCSTATUS_PENDING)
    {   // Either the data phase completed normally (all requested bytes transferred) or 
        // the request did not include a data phase (wLength is zero). Either way:
        //  - Data phase is complete
        //  - Status phase may now be allowed to complete (even if the host has not
        //    specifically started its Status Phase)
        NETCHIP_WRITE(EP_IRQENB, 0);
        EpZero_StatusPhase(Endpoint);
    }
}

#if _NCDEBUG
///////////////////////////////////////////////////////////////////////////////
// Debugging support for printing host's eight-byte setup requests:
//  - Special printf() formatting to add volume controls to setup packets
char SetupPacket_Msg[256];       // Show setup packet message (During debug)
UINT SetupPacket_PrintVolume;    // 
#define SetupPacket_LengthFormat "%-32s Len:%4.4x"
#endif

///////////////////////////////////////////////////////////////////////////////
STATIC void
StandardUsbRequestHandler(
    PNCSTATUS NcStatus
    )
{   // Parse standard USB setup requests:
    //  - If the request is not handled, return status is marked Unsuccessful. Otherwise,
    //    the status is not changed (this makes parsing a little more efficient)
    //  - Parser references a *copy* of Setup Packet read from NET2272. (Firmware 
    //    must not reference the setup packet in the NET2272 because the host may
    //    issue a new setup request at any time!)
    //  - USB lists standard requests (See USB Spec: 9.4)
    static WORDBYTE lewStatus;  // Return status - used as a Little Endian Word
    UINT Length;
    PNC_ENDPOINT_OBJECT Endpoint;

    lewStatus.Word = 0x0000;    // Assume return value is 'success'
    NETCHIP_WRITE(PAGESEL, EP0);
    switch (BMREQUESTTYPE)
    {   // This is a reasonably complete skeleton for handling standard USB setup requests:
        //  - Successful requests should 'return'
        //  - Failed or unhandled requests should 'break' causing endpoint zero to STALL
    case HOST_TO_DEVICE | STANDARD | RECIPIENT_DEVICE:
        switch (BREQUEST)
        {
        case CLEAR_FEATURE:
            // Clear DEVICE Feature
            if (WVALUE == DEVICE_REMOTE_WAKEUP)
            {   // Disable our ability to wake a suspended host
                PrivDeviceObject->HostWakeupEnable = FALSE;
                NCDEBUG(sprintf(SetupPacket_Msg, "CLEAR_FEATURE, DEVICE_REMOTE_WAKEUP");)
                return;
            }
            break;
        case SET_FEATURE:
            // Set DEVICE Feature
            switch(WVALUE)
            {
            case DEVICE_REMOTE_WAKEUP:
                // Enable our ability to wake a suspended host
                PrivDeviceObject->HostWakeupEnable = TRUE;
                NCDEBUG(sprintf(SetupPacket_Msg, "SET_FEATURE, DEVICE_REMOTE_WAKEUP");)
                // Assert: A device that does not report Remote Wakeup capability in its
                // configuration cannot have have its wakeup capability enabled!
                ASSERT(UsbConfiguration->bmAttributes & (1<<5));
                return;

            case TEST_MODE:
                // See USB 2.0: 7.1.20 and 9.4.9 
                //  - USB 2.0: 7.1.20: "The transition to test mode must complete no later than 3ms after
                //    the completion of the status stage of the request." In other words, we don't have 
                //    time to print messages before starting a test mode
                switch(WINDEX_HI) 
                {   
                case USB_TEST_J:
                case USB_TEST_K:
                case USB_TEST_SE0_NAK:
                case USB_TEST_FORCE_ENABLE:
                case USB_TEST_PACKET:
                    NCDEBUG(SetupPacket_PrintVolume = VOLUME_LOW;)
                    NCDEBUG(sprintf(SetupPacket_Msg, "SET_FEATURE, TEST_MODE (Mode:0x%2.2x)", WINDEX_HI);)

                    NcDev_TestMode(WINDEX_HI);
                    return;
                default:
                    break;
                }
                break;
            default:
                break;
            }
            break;
        case SET_ADDRESS:
            // NOTE: USB address changes *after* successful status stage (See USB 1.1: 9.4.6)
            //  - The NET2272 automatically changes the address after status stage
            //  - The address we write now will not updated until *after* the status phase
            //  - USB 2.0: 9.2.6.3: Within 2ms after the status stage of Set Address, the device
            //    must be able to accept packets at the new address. (This can be a gotcha!)
            NETCHIP_WRITE(OURADDR, WVALUE_LO);
            NCDEBUG(SetupPacket_PrintVolume = VOLUME_LOW;)
            NCDEBUG(sprintf(SetupPacket_Msg, "Setting OURADDR:%2.2x", WVALUE_LO);)
            return;
        case SET_CONFIGURATION:
            // Set Configuration:
            //  - Count and initialize endpoints in the configuration
            NcApi_SetConfiguration(PrivDeviceObject);

            // Notify client of Set Configuration event:
            //  - Tip: Most USB devices support configurations zero (de-configured) and 
            //    one (configured). Hosts rarely (except for compliance testing!) issue 
            //    a Set Configuration for configuration zero

⌨️ 快捷键说明

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