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

📄 usbs_sa11x0.c

📁 Sa11的USB驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
                                       (USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {                                ep2_set_halted(&ep2.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 the hardware.                        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_SA11X0_EP1                            else if ((USB_DEVREQ_INDEX_DIRECTION_OUT | 1) == endpoint) {                                ep1_set_halted(&ep1.common, true);                                result = USBS_CONTROL_RETURN_HANDLED;                            }#endif                            #ifdef CYGPKG_DEVS_USB_SA11X0_EP2                            else if ((USB_DEVREQ_INDEX_DIRECTION_IN | 2) == endpoint) {                                ep2_set_halted(&ep2.common, true);                                result = USBS_CONTROL_RETURN_HANDLED;                            }#endif                                                        else {                                result = USBS_CONTROL_RETURN_STALL;                            }                        }                    } // Endpoint or device set-feature                }                // If the result has not been handled yet, pass it to                // the installed callback function (if any).                if (USBS_CONTROL_RETURN_UNKNOWN == result) {                    if ((usbs_control_return (*)(usbs_control_endpoint*, void*))0 != ep0.common.standard_control_fn) {                        result = (*ep0.common.standard_control_fn)(&ep0.common, ep0.common.standard_control_data);                    }                }                #if 1                                if ((USBS_CONTROL_RETURN_UNKNOWN == result) &&                    (USB_DEVREQ_SET_INTERFACE == req->request)) {                                        // This code should not be necessary. For                    // non-trivial applications which involve                    // alternate interfaces and the like, this request                    // should be handled by the application itself.                    // For other applications, the default handler                    // will ignore this request so we end up falling                    // through without actually handling the request                    // and hence returning a stall condition. That                    // is legitimate behaviour according to the standard.                    //                    // However, there are appear to be problems with                    // the SA1110 USB hardware when it comes to stall                    // conditions: they appear to affect some                    // subsequent messages from target to host as                    // well. Hence rather than returning a stall                    // condition this code instead generates a dummy                    // reply, which is also valid according to the                    // standard. This avoids complications with certain                    // USB compliance testers.                    if ((0 != length) ||                        (0 != req->value_hi) || (0 != req->index_hi) ||                        (USBS_STATE_CONFIGURED != (ep0.common.state & USBS_STATE_MASK))) {                                                result = USBS_CONTROL_RETURN_STALL;                    } else {                        int interface_id;                        int alternate;                                    CYG_ASSERT( (1 == ep0.common.enumeration_data->device.number_configurations) && \                                    (1 == ep0.common.enumeration_data->total_number_interfaces),       \                                    "Higher level code should have handled this request");                                    interface_id = req->index_lo;                        alternate    = req->value_lo;                        if ((interface_id != ep0.common.enumeration_data->interfaces[0].interface_id) ||                            (alternate  != ep0.common.enumeration_data->interfaces[0].alternate_setting)) {                            result = USBS_CONTROL_RETURN_STALL;                        } else {                            result = USBS_CONTROL_RETURN_HANDLED;                        }                                            }                }#endif                                // If the result has still not been handled, leave it to                // the default implementation in the USB slave common package                if (USBS_CONTROL_RETURN_UNKNOWN == result) {                    result = usbs_handle_standard_control(&ep0.common);                }                            } else {                // The other three types of control message can be                // handled by similar code.                usbs_control_return (*callback_fn)(usbs_control_endpoint*, void*);                void* callback_arg;                //DBG(("non-standard control request %x", req->request));                                if (USB_DEVREQ_TYPE_CLASS == protocol) {                    callback_fn  = ep0.common.class_control_fn;                    callback_arg = ep0.common.class_control_data;                } else if (USB_DEVREQ_TYPE_VENDOR == protocol) {                    callback_fn  = ep0.common.vendor_control_fn;                    callback_arg = ep0.common.vendor_control_data;                } else {                    callback_fn  = ep0.common.reserved_control_fn;                    callback_arg = ep0.common.reserved_control_data;                }                if ((usbs_control_return (*)(usbs_control_endpoint*, void*)) 0 == callback_fn) {                    result = USBS_CONTROL_RETURN_STALL;                } else {                    result = (*callback_fn)(&ep0.common, callback_arg);                }            }            //DBG(("Control request done, %d\n", result));            if (USBS_CONTROL_RETURN_HANDLED != result) {                // This control request cannot be handled. Generate a stall.                usbs_sa11x0_poke(EP0_CONTROL,                                 EP0_FORCE_STALL | EP0_SERVICED_OPR | EP0_DATA_END,                                 EP0_FORCE_STALL,                                 EP0_OUT_READY);            } else {                // The control request has been handled. Is there any more                // data to be transferred?                if (0 == length) {                    usbs_sa11x0_poke(EP0_CONTROL,                                     EP0_SERVICED_OPR | EP0_DATA_END,                                     EP0_DATA_END,                                     EP0_OUT_READY);                } else {                    // The endpoint should now go into IN or OUT mode while the                    // remaining data is transferred.                    ep0.transmitted     = 0;                    ep0.length          = length;                    if (USB_DEVREQ_DIRECTION_OUT == direction) {                        // Wait for the next packet from the host.                        ep0.ep_state = EP0_STATE_OUT;                        CYG_ASSERT( (unsigned char*) 0 != ep0.common.buffer, "A receive buffer should have been provided");                        CYG_ASSERT( (usbs_control_return (*)(usbs_control_endpoint*, int))0 != ep0.common.complete_fn, \                                    "A completion function should be provided for OUT control messages");                    } else {                        ep0.ep_state = EP0_STATE_IN;                        usbs_sa11x0_ep0_fill_fifo();                    }                }            }   // Control message handled        }       // Received 8-byte control message    }           // Idle state, i.e. control message}               // ep0_dsr#ifdef CYGPKG_DEVS_USB_SA11X0_EP1// ----------------------------------------------------------------------------// Endpoint 1 is used for OUT transfers, i.e. receive operations. Only// the bulk protocol is supported by the hardware. The semantics allow// for two different modes of operation: higher-level code can ask for// exactly one or more bulk packets of 64 bytes each, allowing buffer// requirements to be determined from a header; alternatively the// rx request can just supply a large buffer. Processing the first// packet of a larger transfer separately does not introduce any// special problems at the protocol level.//// It is not legal to receive just part of a packet and expect the// hardware or the driver to buffer the rest. Not all hardware will// be capable of doing this buffering, and there should not be// a driver design requirement to provide buffering space.////// The hardware design for endpoint 1 is flawed in a number of// respects. The receive fifo is only 20 bytes, less than the packet// size, so it is essential to use DMA (there is a configuration// option to allow for communication protocols where packets will// never exceed 16 bytes, but that is not the normal case). The DMA// engine is triggered by a receive-fifo-service high-water mark// bit. DMA transfers operate in bursts of eight bytes. Therefore// it would make sense if the high-water mark was set when the// receive fifo contained eight bytes or more.//// Instead the high-water mark is set when the fifo contains twelve// bytes or more. Worse, there is no way of measuring how many bytes// there are left in the fifo without actually extracting those bytes.//// For a full-size 64-byte packet, the first 56 bytes will be// transferred by DMA and the remainder will remain in the fifo. For a// partial packet of between 56 and 63 bytes, the first 56 bytes will// be transferred by DMA and the remainder will remain in the fifo. There// is no way to distinguish between these scenarios without emptying// the fifo.//// The result is that there is never any point in attempting a DMA// transfer of more than 56 bytes, and for every endpoint 1 interrupt// it is necessary to read the remainder from the fifo. This adds// a lot of software overhead, and it is not clear that DMA is// particularly useful. It is still necessary because of the limited// fifo size.////// Because DMA involves the use of physical rather than virtual// memory, there are also cache interaction problems. Specifically it// would be necessary to invalidate cache lines after a DMA transfer// has completed, but that only works sensibly if the buffer is// aligned to a cache-line boundary and is a multiple of the// cache-line size. Imposing such restrictions on higher-level code// is undesirable. Also the DMA engines have an apparently undocumented// restriction that the buffer must be eight-byte aligned.//// To work around all these problems, the receive code works in terms// of a small private buffer. After a packet has been received, data// will be copied from this private buffer to the destination. Obviously// this copy operation is overhead and, because the code is expected// to run at DSR level, However the copy operation is limited to at// most 64 bytes, which is not good but not disastrous either.//// For data transfers the entry points are://// 1) ep1_start_rx_packet() - prepare to receive another packet from//    the host.// 2) ep1_clear_error() - an error condition has occurred (CRC,//    bit-stuffing, fifo overrun). It appears that the only way//    to clear this is to clear the receive-packet-complete bit,//    which unfortunately allows in another packet from the host//    before we are ready for it. Doing anything else while//    the error bit is set does not work, for example it is not//    possible to empty the fifo by hand.// 3) ep1_process_packet() - a whole packet has been received//    and now needs to be moved into application space.//// These three routines are called by the start_rx() routine and// by the DSR. There are different implementations for DMA and// non-DMA.//// There is another hardware problem: the receive-packet-complete bit// comes up with the wrong default value, allowing the host to start// transmitting before the target is ready to receive. Unfortunately// there is not much that can be done about this: the// receive-packet-complete bit cannot be set by software and the OUT// max register has a minimum size of eight bytes. Fortunately for// many protocols the target-side code has a chance to start a receive// before the host is allowed to send, so this problem is mostly// ignored for now.//// Another potential problem arises if the host sends more data than// is expected for a given transfer. It would be possible to address// this by manipulating the OUT max packet register and getting the// hardware to generate protocol violation stalls. This would also// eliminate the need to test for buffer overflows. For now it is// left to higher-level code to sort it a

⌨️ 快捷键说明

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