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

📄 usbs_upd985xx.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
}

// An endpoint 0 receive has completed. This could be a new control
// message. Or it could be the data for a previous control message. Or
// it could be a new control message when expecting the data from
// a previous one. The ep0.rx_expecting_data field indicates
// whether or not a new control message is expected.
//
// At times an interrupt triggers and there is an rx indication for a
// zero-byte transfer. Such a transfer may be followed immediately by
// a real transfer. It is not understood why the zero-byte transfer
// occurs. They are ignored by the drain_rx_mailbox() code, to make
// sure that there is at most one valid rx indicator at a time.
static void
ep0_rx_dsr(void)
{
    // Start by checking the rx indicator to make sure that a packet
    // really has been received.
    if (!ep0.rx_indicator_valid) {
        drain_rx_mailbox();
        if (!ep0.rx_indicator_valid) {
            // Do not assert, in case of a spurious interrupt for a
            // zero-byte transfer.
            return;
        }
    }
    
    // We have a valid receive, with the data held in uncached->ep0_rx_buffer.
    // Are we expecting the remaining data of a control transfer?
    if (ep0.rx_expecting_data) {
        // Was this data interrupted by a new setup packet?
        if (0 != (ep0.rx_indicator.status & RXMBOX_STATUS_SETUP_SETUP)) {
            // NOTE: it is not clear from the documentation exactly what
            // happens here, e.g. is it guaranteed that the new control
            // packet appears at the start of the buffer rather than
            // after any data previously received? Given typical
            // USB host-side implementations this scenario is considered
            // sufficiently unlikely that no further investigation has
            // been carried out.
            
            // Inform higher-level code that the receive has been aborted.
            if ((usbs_control_return (*)(usbs_control_endpoint*, int)) 0 != ep0.common.complete_fn) {
                (*ep0.common.complete_fn)(&ep0.common, -EIO);
            }
            ep0.rx_expecting_data       = false;
            ep0.common.buffer           = (unsigned char*) 0;
            ep0.common.buffer_size      = 0;
            ep0.common.fill_buffer_fn   = 0;
            ep0.common.complete_fn      = (usbs_control_return (*)(usbs_control_endpoint*, int)) 0;
            // Fall through the main control message handling code below.
        } else {
            // Data was expected and received. Transfer the data to the
            // user's buffer, and perform completion.
            usbs_control_return result;
            cyg_uint32          size     = ep0.rx_indicator.status & RXMBOX_STATUS_SIZE_MASK;
            
            CYG_ASSERT( (usbs_control_return (*)(usbs_control_endpoint*, int))0 != ep0.common.complete_fn, \
                        "A completion function should be provided for OUT control messages");
            CYG_ASSERT(size == ep0.common.buffer_size, "Inconsistency between buffer and transfer sizes");
            memcpy(ep0.common.buffer, uncached->ep0_rx_buffer, size);
            result = (*ep0.common.complete_fn)(&ep0.common, 0);
            ep0.common.buffer           = (unsigned char*) 0;
            ep0.common.buffer_size      = 0;
            ep0.common.complete_fn      = (usbs_control_return (*)(usbs_control_endpoint*, int)) 0;
            ep0.rx_expecting_data       = false;

            // Start another receive for the next control message.
            // Note that there has been a window where there was no receive
            // in progress for endpoint 0, even though according to the
            // USB spec a device must always be able to accept new
            // control messages.
            ep0_start_rx(8);
            return;
        }
    }

    // When we get here we should have an eight-byte control message
    // in uncached->ep0_rx_buffer. This should get moved into
    // the ep0.common.control_buffer so that higher-level code sees
    // it in the appropriate location.
    CYG_ASSERT((ep0.rx_indicator.address == &(uncached->ep0_rx_bufdescs[0])) || \
               (ep0.rx_indicator.address == &(uncached->ep0_rx_bufdescs[2])),   \
               "Received ep0 data should involve the ep0 rx buffer descriptor");
    
    CYG_ASSERT(8 == (ep0.rx_indicator.status & RXMBOX_STATUS_SIZE_MASK), "Control messages should be 8 bytes");
    memcpy(ep0.common.control_buffer, uncached->ep0_rx_buffer, 8);

    // If we have received a control packet then any reset signals really
    // will have come from the host and must be processed normally.
    // Make sure that reset interrupts are no longer masked off.
    if (0 == (*USBS_IMR2 & IBUS_SWAP32(USBS_GSR2_URST))) {
        *USBS_IMR2              |= IBUS_SWAP32(USBS_GSR2_URST); FLUSH_IBUS();
        usbs_upd985xx_gsr2_mask |= USBS_GSR2_URST;
    }
    
    {
        usbs_control_return result  = USBS_CONTROL_RETURN_UNKNOWN;
        usb_devreq*         req     = (usb_devreq*) ep0.common.control_buffer;
        int length, direction, protocol, recipient;
            
        // Now we need to do some decoding of the data. A non-zero
        // length field indicates that there will be a subsequent
        // IN or OUT phase. The direction is controlled by the
        // top bit of the first byte. The protocol is determined
        // by other bits of the top byte.
        length      = (req->length_hi << 8) | req->length_lo;
        direction   = req->type & USB_DEVREQ_DIRECTION_MASK;
        protocol    = req->type & USB_DEVREQ_TYPE_MASK;
        recipient   = req->type & USB_DEVREQ_RECIPIENT_MASK;

        DBG(("ep0, new control request: type %x, code %x\n", req->type, req->request));
        DBG(("     %s, length %d, value hi %x lo %x, index hi %x lo %x\n",
             (USB_DEVREQ_DIRECTION_OUT == direction) ? "out" : "in",
             length, req->value_hi, req->value_lo, req->index_hi, req->index_lo));

        if (USB_DEVREQ_TYPE_STANDARD == protocol) {
                
            // First see if the request can be handled entirely in
            // this module.
            if (USB_DEVREQ_SET_ADDRESS == req->request) {
                // The USB device address should be in value_lo.
                // No more data is expected.
                int old_state = ep0.common.state;
                int address = req->value_lo;
                if ((0 != length) || (address > 127)) {
                    result = USBS_CONTROL_RETURN_STALL;
                } else {
                    *USBS_GMR = (*USBS_GMR & ~(USBS_GMR_FA_MASK | USBS_GMR_VT)) | (address << USBS_GMR_FA_SHIFT); FLUSH_IBUS();
                    result = USBS_CONTROL_RETURN_HANDLED;
                }
                // Switch to addressed state, informing higher-level
                // code of this.
                if (USBS_STATE_ADDRESSED != (old_state & USBS_STATE_MASK)) {
                    ep0.common.state        = USBS_STATE_ADDRESSED;
                    if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != ep0.common.state_change_fn) {
                        (*ep0.common.state_change_fn)(&ep0.common, ep0.common.state_change_data,
                                                      USBS_STATE_CHANGE_ADDRESSED, old_state);
                    }
                }
                // End of SET_ADDRESS handling
            } else if (USB_DEVREQ_GET_STATUS == req->request) {
                // GET_STATUS on the device as a whole is used to
                // check the remote-wakeup and self-powered bits.
                // GET_STATUS on an endpoint is used to determine
                // the halted condition.
                // GET_STATUS on anything else has to be left to
                // other code.
                if (USB_DEVREQ_RECIPIENT_DEVICE == recipient) {
                    // The host should expect two bytes back.
                    if ((2 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
                        ep0.common.control_buffer[0] = 0;   // Not self-powered, no remote wakeup
                        ep0.common.control_buffer[1] = 0;
                        ep0.common.buffer            = ep0.common.control_buffer;
                        ep0.common.buffer_size       = 2;
                        result                       = USBS_CONTROL_RETURN_HANDLED;
                    } else {
                        result = USBS_CONTROL_RETURN_STALL;
                    }
                        
                } else if (USB_DEVREQ_RECIPIENT_ENDPOINT == recipient) {
                    if ((2 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
                        int endpoint = req->index_lo;
                        if (0 == endpoint) {
                            // get-status on endpoint 0 is either undefined or always valid.
                            // endpoint 0 is always up.
                            ep0.common.control_buffer[0] = 0;
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3
                        else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 3) == endpoint) &&
                                 (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
                            ep0.common.control_buffer[0] = ep3.common.halted;
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#endif                            
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4
                        else if (((USB_DEVREQ_INDEX_DIRECTION_OUT | 4) == endpoint) &&
                                 (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
                            ep0.common.control_buffer[0] = ep4.common.halted;
                            result = USBS_CONTROL_RETURN_HANDLED;
                                
                        }
#endif                            
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP5
                        else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 5) == endpoint) &&
                                 (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
                            ep0.common.control_buffer[0] = ep5.common.halted;
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#endif                            
                        else {
                            // An invalid endpoint has been specified or the
                            // endpoint can only be examined in configured state.
                            result = USBS_CONTROL_RETURN_STALL;
                        }
                        if (USBS_CONTROL_RETURN_HANDLED == result) {
                            ep0.common.control_buffer[1] = 0;
                            ep0.common.buffer            = ep0.common.control_buffer;
                            ep0.common.buffer_size       = 2;
                        }
                    } else {
                        result = USBS_CONTROL_RETURN_STALL;
                    }
                } // Endpoint or device get-status
                    
            } else if (USB_DEVREQ_CLEAR_FEATURE == req->request) {

                // CLEAR_FEATURE operates in much the same way as
                // GET_STATUS
                if (USB_DEVREQ_RECIPIENT_DEVICE == recipient) {
                        
                    // No data should be transferred, and only remote-wakeup can be cleared.
                    if ((0 != length) || (USB_DEVREQ_FEATURE_DEVICE_REMOTE_WAKEUP != req->value_lo)) {
                        result = USBS_CONTROL_RETURN_STALL;
                    } else {
                        // Clearing remote-wakeup is a no-op.
                        result = USBS_CONTROL_RETURN_HANDLED;
                    }

                } else if (USB_DEVREQ_RECIPIENT_ENDPOINT == recipient) {
                    // The only feature that can be cleared is endpoint-halt, no data should be transferred.
                    if ((0 != length) || (USB_DEVREQ_FEATURE_ENDPOINT_HALT != req->value_lo)) {
                        result = USBS_CONTROL_RETURN_STALL;
                    } else {
                        int endpoint = req->index_lo;
                        if (0 == endpoint) {
                            // Clearing halt on endpoint 0 is always a no-op since that endpoint cannot be halted
                        }
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3
                        else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 3) == endpoint) &&
                                 (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
                            ep3_set_halted(&ep3.common, false);
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4
                        else if (((USB_DEVREQ_INDEX_DIRECTION_OUT | 4) == endpoint) &&
                                 (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
                            ep4_set_halted(&ep4.common, false);
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP5
                        else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 5) == endpoint) &&
                                 (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
                            ep5_set_halted(&ep5.common, false);
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#endif
                        else {
                            // Invalid endpoint or not in configured state.
                            result = USBS_CONTROL_RETURN_STALL;
                        }
                    }
                }   // Endpoing or device clear-feature
                    
            } else if (USB_DEVREQ_SET_FEATURE == req->request) {

                // SET_FEATURE also operates in much the same way as
                // GET_STATUS
                if (USB_DEVREQ_RECIPIENT_DEVICE == recipient) {
                    // The only valid feature that can be set is remote-wakeup,
                    // which is not supported by this driver.
                    result = USBS_CONTROL_RETURN_STALL;
                        
                } else if (USB_DEVREQ_RECIPIENT_ENDPOINT == recipient) {

                    // Only the halt condition can be set, and no data should be transferred.
                    // Halting endpoint 0 should probably be disallowed although the
                    // standard does not explicitly say so.
                    if ((0 != length) ||
                        (USB_DEVREQ_FEATURE_ENDPOINT_HALT != req->value_lo) ||
                        (USBS_STATE_CONFIGURED != (ep0.common.state & USBS_STATE_MASK))) {
                            
                        result = USBS_CONTROL_RETURN_STALL;
                            
                    } else {
                        int endpoint = req->index_lo;
                        if (0) {
                        }
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3
                        else if ((USB_DEVREQ_INDEX_DIRECTION_IN | 3) == endpoint) {
                            ep3_set_halted(&ep3.common, true);
                            result = USBS_CONTROL_RETURN_HANDLED;
                        }
#endif                            
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4
 

⌨️ 快捷键说明

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