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

📄 usbs_sa11x0.c

📁 Sa11的USB驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
                buf[emptied] = *EP0_DATA;                for (checks = 0; !read && (checks < MAX_CHECKS); checks++) {                    if ((count - emptied) > *EP0_WRITE_COUNT) {                        //DBG(("Read %d byte (%x) after %d checks, %d retries\n", emptied, buf[emptied], checks, retries));                        read = true;                        emptied++;                    }                }            }        }        if (ok && !read) {            DBG(("EP0 empty fifo, failed to read byte from fifo\n"));            ok = false;        }    }        return emptied;}// This is where all the hard work happens. It is a very large routine// for a DSR, but in practice nearly all of it is nested if's and very// little code actually gets executed. Note that there may be// invocations of callback functions and the driver has no control// over how much time those will take, but those callbacks should be// simple.static voidusbs_sa11x0_ep0_dsr(void){    int hw_state = *EP0_CONTROL;    // Handle the stall bits.    //    // Force-stall should not be a problem. It is set by the code here    // if the host needs to be told that the control message was    // unacceptable and is cleared automatically by the hardware after    // the stall is sent.    // NOTE: it is not clear the hardware actually works in this    // respect. The FORCE_STALL bit has been observed still set during    // the next interrupt, and the host appears to receive spurious    // data back in response to the next control packet.    //    // Sent-stall is set by the hardware following a protocol    // violation, e.g. if there is an IN token when a new control    // message is expected. There is nothing the software can do about    // this. However if we are in the middle of an IN or OUT transfer    // then those are not going to complete successfully.    if (0 != (hw_state & EP0_SENT_STALL)) {        if (EP0_STATE_IDLE != ep0.ep_state) {            if ((usbs_control_return (*)(usbs_control_endpoint*, int))0 != ep0.common.complete_fn) {                (*ep0.common.complete_fn)(&ep0.common, -EIO);            }            ep0.ep_state                = EP0_STATE_IDLE;            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;        }        usbs_sa11x0_poke(EP0_CONTROL, EP0_SENT_STALL, 0, EP0_SENT_STALL);    }   // STALL condition        // Next, check whether we have received a new control message    // while still busy processing an old one.    if (0 != (hw_state & EP0_SETUP_END)) {        if (EP0_STATE_IDLE != ep0.ep_state) {            if ((usbs_control_return (*)(usbs_control_endpoint*, int)) 0 != ep0.common.complete_fn) {                (*ep0.common.complete_fn)(&ep0.common, -EIO);            }            ep0.ep_state                = EP0_STATE_IDLE;            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;        }        // We are now back in idle state so the control message will be        // extracted and processed.        usbs_sa11x0_poke(EP0_CONTROL, EP0_SERVICED_SETUP_END, 0, EP0_SETUP_END);    }   // Interrupted control transaction    // The endpoint can be in one of three states: IN, OUT, or IDLE.    // For the first two it should mean that there is more data to be    // transferred, which is pretty straightforward. IDLE means    // that a new control message has arrived.    if ((EP0_STATE_IN == ep0.ep_state) && (0 == (EP0_IN_READY & hw_state)))  {                usbs_sa11x0_ep0_fill_fifo();            } else if ((EP0_STATE_OUT == ep0.ep_state) && (0 != (EP0_OUT_READY & hw_state))) {        // A host->device transfer. Higher level code must have        // provided a suitable buffer.        CYG_ASSERT( (unsigned char*)0 != ep0.common.buffer, "A receive buffer should have been provided" );        ep0.transmitted += usbs_sa11x0_ep0_empty_fifo(ep0.common.buffer + ep0.transmitted);        if (ep0.transmitted != ep0.length) {            // The host is not allowed to send more data than it            // indicated in the original control message, and all            // messages until the last one should be full size.            CYG_ASSERT( ep0.transmitted < ep0.length, "The host must not send more data than expected");            CYG_ASSERT( 0 == (ep0.transmitted % EP0_FIFO_SIZE), "All OUT packets until the last one should be full-size");            usbs_sa11x0_poke(EP0_CONTROL, EP0_SERVICED_OPR, 0, EP0_OUT_READY);        } else {            // The whole transfer is now complete. Invoke the            // completion function, and based on its return value            // either generate a stall or complete the message.            usbs_control_return result;                        CYG_ASSERT( (usbs_control_return (*)(usbs_control_endpoint*, int))0 != ep0.common.complete_fn, \                        "A completion function should be provided for OUT control messages");            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;                        if (USBS_CONTROL_RETURN_HANDLED == result) {                usbs_sa11x0_poke(EP0_CONTROL,                                 EP0_SERVICED_OPR | EP0_DATA_END,                                 EP0_DATA_END,                                 EP0_OUT_READY);            } else {                usbs_sa11x0_poke(EP0_CONTROL,                                 EP0_SERVICED_OPR | EP0_DATA_END | EP0_FORCE_STALL,                                 EP0_FORCE_STALL,                                 EP0_OUT_READY);            }            // Also remember to switch back to IDLE state             ep0.ep_state = EP0_STATE_IDLE;        }            } else if (0 != (EP0_OUT_READY & hw_state)) {        int emptied = usbs_sa11x0_ep0_empty_fifo(ep0.common.control_buffer);                if (8 != emptied) {            // This indicates a serious problem somewhere. Respond by            // stalling. Hopefully the host will take some action that            // sorts out the mess.            usbs_sa11x0_poke(EP0_CONTROL,                             EP0_SERVICED_OPR | EP0_DATA_END | EP0_FORCE_STALL,                             EP0_FORCE_STALL,                             EP0_OUT_READY);                    } else {            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;#if 0            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));#endif                        if (0 != length){                // Clear the fifo straightaway. There is no harm in                // doing this here. It may or may not do some good.                usbs_sa11x0_poke(EP0_CONTROL, EP0_SERVICED_OPR, 0, EP0_OUT_READY);            }                        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 address = req->value_lo;                    if ((0 != length) || (address > 127)) {                        result = USBS_CONTROL_RETURN_STALL;                    } else {                        // poke_value() cannot be used here because                        // setting the address does not take effect                        // until the status phase.                        *USBS_ADDRESS = address;                        result = USBS_CONTROL_RETURN_HANDLED;                    }                } 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_SA11X0_EP1                            else if (((USB_DEVREQ_INDEX_DIRECTION_OUT | 1) == endpoint) &&                                       (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {                                                                ep0.common.control_buffer[0] = ep1.common.halted;                                result = USBS_CONTROL_RETURN_HANDLED;                            }#endif                            #ifdef CYGPKG_DEVS_USB_SA11X0_EP2                            else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 2) == endpoint) &&                                       (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {                                ep0.common.control_buffer[0] = ep2.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_SA11X0_EP1                            else if (((USB_DEVREQ_INDEX_DIRECTION_OUT | 1) == endpoint) &&                                       (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {                                ep1_set_halted(&ep1.common, false);                                result = USBS_CONTROL_RETURN_HANDLED;                                                            }#endif#ifdef CYGPKG_DEVS_USB_SA11X0_EP2                            else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 2) == endpoint) &&

⌨️ 快捷键说明

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