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

📄 usbs.h

📁 开放源码实时操作系统源码.
💻 H
📖 第 1 页 / 共 2 页
字号:
    // functions. However in simple devices those device-specific
    // state change functions could be invoked directly.
    void                (*state_change_fn)(struct usbs_control_endpoint*, void*, usbs_state_change, int /* old state */);
    void*               state_change_data;
    // When a standard control message arrives, the device driver will
    // detect some requests such as SET_ADDRESS and handle it
    // internally. Otherwise if higher-level code has installed a
    // callback then that will be invoked. If the callback returns
    // UNKNOWN then the default handler usbs_handle_standard_control()
    // is used to process the request. 
    usbs_control_return (*standard_control_fn)(struct usbs_control_endpoint*, void*);
    void*               standard_control_data;
    
    // These three callbacks are used for other types of control
    // messages. The generic USB code has no way of knowing what
    // such control messages are about.
    usbs_control_return (*class_control_fn)(struct usbs_control_endpoint*, void*);
    void*               class_control_data;
    usbs_control_return (*vendor_control_fn)(struct usbs_control_endpoint*, void*);
    void*               vendor_control_data;
    usbs_control_return (*reserved_control_fn)(struct usbs_control_endpoint*, void*);
    void*               reserved_control_data;

    // If a control operation involves transferring more data than
    // just the initial eight-byte packet, the following fields are
    // used to keep track of the current operation. The original
    // control request indicates the direction of the transfer (IN or
    // OUT) and a length field. For OUT this length is exact, for IN
    // it is an upper bound. The transfer operates mostly as per the
    // bulk protocol, but if the length requested is an exact multiple
    // of the control fifo size (typically eight bytes) then there
    // is no need for an empty packet at the end.
    //
    // For an OUT operation the control message handler should supply
    // a suitable buffer via the "buffer" field below. The only other
    // field of interest is the complete_fn which must be provided and
    // will be invoked once all the data has arrived. Alternatively
    // the OUT operation may get aborted if a new control message
    // arrives. The second argument is an error code -EPIPE or -EIO,
    // or zero to indicate success. The return code is used by the
    // device driver during the status phase.
    //
    // IN is more complicated and the defined interface makes it
    // possible to gather data from multiple locations, eliminating
    // the need for copying into large buffers in some circumstances.
    // Basically when an IN request arrives the device driver will
    // look at the buffer and buffer_size fields, extracting data from
    // there if possible. If the current buffer has been exhausted
    // then the the refill function will be invoked, and this can
    // reset the buffer and size fields to point somewhere else. 
    // This continues until such time that there is no longer
    // a refill function and the current buffer is empty. The
    // refill function can use the refill_data and refill_index
    // to keep track of the current state. The control_buffer
    // fields are available as well. At the end of the transfer,
    // if a completion function has been supplied then it will
    // be invoked. The return code will be ignored.
    unsigned char*      buffer;
    int                 buffer_size;
    void                (*fill_buffer_fn)(struct usbs_control_endpoint*);
    void*               fill_data;
    int                 fill_index;
    usbs_control_return (*complete_fn)(struct usbs_control_endpoint*, int);
} usbs_control_endpoint;

// Data endpoints are a little bit simpler, but not much. From the
// perspective of a device driver things a single buffer is most
// convenient, but that is quite likely to require a max-size buffer
// at a higher level and an additional copy operation. Supplying
// a vector of buffers is a bit more general, but in a layered
// system it may be desirable to prepend to this vector...
// A combination of a current buffer and a refill/empty function
// offers flexibility, at the cost of additional function calls
// from inside the device driver.
//
// FIXME: implement support for fill/empty functions.
//
// Some USB devices may prefer buffers of particular alignment,
// e.g. for DMA purposes. This is hard to reconcile with the
// current interface. However pushing such alignment restrictions
// etc. up into the higher levels is difficult, e.g. it does
// not map at all onto a conventional read/write interface.
// The device driver will just have to do the best it can.
//
// The completion function will be invoked at the end of the transfer.
// The second argument indicates per-transfer completion data. The
// third argument indicates the total amount received, or an error
// code: typically -EPIPE to indicate a broken conenction; -EAGAIN to
// indicate a stall condition; -EMSGSIZE if the host is sending more
// data than the target is expecting; or -EIO to indicate some other
// error. Individual device drivers should avoid generating other
// errors.
typedef struct usbs_rx_endpoint {
    void                (*start_rx_fn)(struct usbs_rx_endpoint*);
    void                (*set_halted_fn)(struct usbs_rx_endpoint*, cyg_bool);
    void                (*complete_fn)(void*, int);
    void*               complete_data;
    unsigned char*      buffer;
    int                 buffer_size;
    cyg_bool            halted;
} usbs_rx_endpoint;

typedef struct usbs_tx_endpoint {
    void                (*start_tx_fn)(struct usbs_tx_endpoint*);
    void                (*set_halted_fn)(struct usbs_tx_endpoint*, cyg_bool);
    void                (*complete_fn)(void*, int);
    void*               complete_data;
    const unsigned char*buffer;
    int                 buffer_size;
    cyg_bool            halted;
} usbs_tx_endpoint;

// Functions called by device drivers.
extern usbs_control_return usbs_handle_standard_control(struct usbs_control_endpoint*);
    
// Utility functions. These just invoke the corresponding function
// pointers in the endpoint structures. It is assumed that the
// necessary fields in the endpoint structures will have been
// filled in already.
extern void     usbs_start(usbs_control_endpoint*);
extern void     usbs_start_rx(usbs_rx_endpoint*);
extern void     usbs_start_tx(usbs_tx_endpoint*);
extern void     usbs_start_rx_buffer(usbs_rx_endpoint*, unsigned char*, int, void (*)(void*, int), void*);
extern void     usbs_start_tx_buffer(usbs_tx_endpoint*, const unsigned char*, int, void (*)(void*, int), void*);
extern cyg_bool usbs_rx_endpoint_halted(usbs_rx_endpoint*);
extern cyg_bool usbs_tx_endpoint_halted(usbs_tx_endpoint*);
extern void     usbs_set_rx_endpoint_halted(usbs_rx_endpoint*, cyg_bool);
extern void     usbs_set_tx_endpoint_halted(usbs_tx_endpoint*, cyg_bool);
extern void     usbs_start_rx_endpoint_wait(usbs_rx_endpoint*, void (*)(void*, int), void*);
extern void     usbs_start_tx_endpoint_wait(usbs_tx_endpoint*, void (*)(void*, int), void*);
    
// Functions that can go into devtab entries. These should not be
// called directly, they are intended only for use by USB device
// drivers.
#if defined(CYGPKG_IO) && defined(CYGPKG_ERROR)
#include <cyg/io/io.h>
extern Cyg_ErrNo usbs_devtab_cwrite(cyg_io_handle_t, const void*, cyg_uint32*);
extern Cyg_ErrNo usbs_devtab_cread(cyg_io_handle_t, void*, cyg_uint32*);
extern Cyg_ErrNo usbs_devtab_get_config(cyg_io_handle_t, cyg_uint32, void*, cyg_uint32*);
extern Cyg_ErrNo usbs_devtab_set_config(cyg_io_handle_t, cyg_uint32, const void*, cyg_uint32*);
#endif

// Additional support for testing.
// Test cases need to have some way of finding out about what support is
// actually provided by the USB device driver, for example what endpoints
// are available. There is no perfect way of achieving this. One approach
// would be to scan through the devtab table looking for devices of the
// form /dev/usbs1r. That is not reliable: the devtab entries may have been
// configured out if higher-level code uses the usb-specific API; or the
// devtab entries may have been renamed. Also having a devtab entry does not
// really give the kind of information a general-purpose testcase needs,
// for example upper bounds on transfer size.    
// 
// An alternative approach is to have a data structure that somehow
// defines the USB hardware, and the USB device driver then creates an
// instance of this. This is the approach actually taken. The problem
// now is how the test code can access this instance. Accessing by
// unique name is simple, as long as there is only one USB device in
// the system (which of course will usually be the case on the USB
// slave side). Alternative approaches such as creating a table at
// link time or a list during static construction time are vulnerable
// either to selective linking or to having these structures present
// in applications other than the test cases. In future it might be
// possible to address the latter issue by extending the build system
// support, e.g. a new library libtesting.a and a new object file
// testing.o.
//
// Note that a given endpoint could be used for bulk transfers some
// of the time, then for isochronous transfers, etc. It is the
// responsibility of the host to only perform one type of IN operation
// for a given endpoint number, and ditto for OUT.    

typedef struct usbs_testing_endpoint {
    int         endpoint_type;          // One of ATTR_CONTROL, ATTR_BULK, ...
    int         endpoint_number;        // Between 0 and 15
    int         endpoint_direction;     // ENDPOINT_IN or ENDPOINT_OUT
    void*       endpoint;               // pointer to the usbs_control_endpoint, usbs_rx_endpoint, ...
    const char* devtab_entry;           // e.g. "/dev/usbs1r", or 0 if inaccessible via devtab
    int         min_size;               // Minimum transfer size
    int         max_size;               // -1 indicates no specific upper bound
    int         max_in_padding;         // extra bytes that the target may send, usually 0.
                                        // Primarily for SA11x0 hardware. It is assumed
                                        // for now that no other hardware will exhibit
                                        // comparable problems.
    int         alignment;              // Buffer should be aligned to a suitable boundary
} usbs_testing_endpoint;

// A specific instance provided by the device driver. The end of
// the table is indicated by a NULL endpoint field.    
extern usbs_testing_endpoint usbs_testing_endpoints[];    

#define USBS_TESTING_ENDPOINTS_TERMINATOR                           \
    {                                                               \
        endpoint_type       : USB_ENDPOINT_DESCRIPTOR_ATTR_CONTROL, \
        endpoint_number     : 0,                                    \
        endpoint_direction  : USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN,  \
        endpoint            : (void*) 0,                            \
        devtab_entry        : (const char*) 0,                      \
        min_size            : 0,                                    \
        max_size            : 0,                                    \
        max_in_padding      : 0,                                    \
        alignment           : 0                                     \
    }

#define USBS_TESTING_ENDPOINTS_IS_TERMINATOR(_endpoint_) ((void*)0 == (_endpoint_).endpoint)
    
#ifdef __cplusplus
} // extern "C" {
#endif

#endif // CYGONCE_USBS_H

⌨️ 快捷键说明

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