On Fri, 2002-01-18 at 05:36, Bj�rn Stenberg wrote:
> Hi.
> 
> What is the current status of usb slave mode support? I googled around a
> bit but only found references to some of the recent PDA projects.
> 
> -- 
> Bj�rn
> 

Hi,

I searched a while back and found a few USB slave implementations, but
they seemed to make a lot of assumptions based on the capabilities of
the h/w and the device type.

So I started working on a general USB slave framework.

The big split in the architecture is between the hardware-specific
module which implements the API and the "Functional Drivers" which use
it. By Functional Drivers I mean tha counterpart to the Class Drivers
which run on the host. Examples include a driver implementing the device
side of a Mass Storage Class or an Audio Class.

If possible, I'd like to get people doing USB slave implementations to
start converging on a platform-independent API and get it into the main
kernel source tree. To this end I'm attaching the header file which
defines my API and some starter specs. At this point I have a partial
implementatin on a particular h/w platform but do not yet have
permission to release it GPL.

Comments are welcome.

Regards,
--gmcnutt
/*****************************************************************************
  NAME
        usb_client.h -- interface to the usb client driver

  DESCRIPTION
        Defines usage of the usb client core driver. Intended for functional
        drivers or other upper layer entities.

  AUTHOR
        <[EMAIL PROTECTED]>

  COPYRIGHT:
          (C) 2002 RidgeRun, Inc. (http://www.ridgerun.com)
 
  This program is free software; you can redistribute  it and/or modify it
  under  the terms of  the GNU General  Public License as published by the
  Free Software Foundation;  either version 2 of the  License, or (at your
  option) any later version.
 
  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  You should have received a copy of the  GNU General Public License along
  with this program; if not, write  to the Free Software Foundation, Inc.,
  675 Mass Ave, Cambridge, MA 02139, USA.
 
 *****************************************************************************/

 *****************************************************************************/
#ifndef uc_h
#define uc_h

#include <linux/types.h>
#include <linux/list.h>

//////////////////////////////////////////////////////////////////////////////
// The packet interface
//
// Data transfer between the upper layers and the core is accomplished via
// packets. 'Packets' are really 'buffers', and don't necessarily have any
// correlation with USB packets.
//
// On receive, callers should always submit a buffer large enough to hold the
// next expected transaction (the core has no way of knowing how big this is,
// usually it's defined by a higher-level protocol). The core will fill it until
// it runs out of room (in which case it sets the UCF_OVERRUN flag before
// returning it) or it receives a complete transaction (in which case it sets
// the UCF_EOT flag).
//
// If a buffer cannot be sent or filled for some reason (e.g., cable 
// disconnect or configuration change) then the core sets the UCF_ABORT flag
// and returns all submitted pacekts.
//
// On send, the core will treat the buffer as one complete transaction. In
// the case of multiple submitted transmit buffers they are sent in the same
// order they were submitted, each as its own transaction.
//
// In all cases, when the core is done with a buffer it returns it by invoking
// the buffer's callback. Note the danger of unloading an upper layer module
// when it has packets submitted -- the usage model for client USB is to
// *never* unload class driver modules (I realize this may be a pain for
// debugging, so I might add a 'flush' call to address this later...).
//////////////////////////////////////////////////////////////////////////////

// Packet flags:
#define UCF_EOT     (1 << 0) // End of transfer (short or zero-length pkt)
#define UCF_ABORT   (1 << 1) // packet canceled
#define UCF_OVERRUN (1 << 2) // host sent more data than buffer can hold

struct uc_pkt;

typedef void (*uc_pkt_cb_t)(struct uc_pkt *pkt);

typedef struct uc_pkt {

        struct list_head list; // used by core
        uc_pkt_cb_t cb;        // called by core when done
        void *private;         // owner's optional data (untouched by core)

        u8 *data;   // data pointer (set by owner)
        u8 *ptr;    // pointer to next byte to send/receive
        u16 len;    // max length of data buffer (set by owner)
        u16 n;      // actual length of data in buffer

        u8  ep;     // endpoint # (set by owner)
        u8  cfg;    // configuration # (set by owner)
        u16 flags;  // flags (set by core)

} uc_pkt_t;

extern int uc_tx(uc_pkt_t *pkt);
extern int uc_rx(uc_pkt_t *pkt);
extern void uc_halt(u8 cfg, u8 ep);
extern void uc_flush(u8 cfg, u8 ep);

//////////////////////////////////////////////////////////////////////////////
// The notifier interface
//
// The core can asynchronously notify upper layers when certain events occur.
// Upper layers must register notifiers with the core in order to receive
// events. Note that sometimes the core will call notifiers from within an
// ISR (evil, but it greatly simplifies some circumstances that would
// otherwise be rife with race conditions).
//////////////////////////////////////////////////////////////////////////////

// Event types:
#define UCE_CLASS_REQ    (1 << 0) // Class Device Request
#define UCE_VENDOR_REQ   (1 << 1) // Vendor Device Request
#define UCE_CFG_CHANGE   (1 << 2) // SetConfiguration event, data is new cfg

struct uc_notifier;

typedef void (*uc_notify_cb_t)(struct uc_notifier *notifier, u8 event, 
                               void *data);

typedef struct uc_notifier {
        struct list_head list; // used by core
        uc_notify_cb_t cb;     // called by core when filtered event occurs
        u8 filter;             // bitmask of desired events
        u8 cfg;                // configuration of notifiee (for UCE_CLASS_REQ)
} uc_notifier_t;

extern void uc_register_notifier(uc_notifier_t *notifier);
extern void uc_unregister_notifier(uc_notifier_t *notifier);

//////////////////////////////////////////////////////////////////////////////
// The descriptor interface
//
// Class drivers need to register descriptors with the core. The descriptor
// should be a raw byte stream layed out in little-endian order exactly the
// way the core should send it over the wire. The core will make absolutely
// *no* modifications to descriptors submitted by the upper layer. In fact,
// it doesn't even make its own copy -- so it's best for class drivers to
// submit a pointer to a static const buffer.
//////////////////////////////////////////////////////////////////////////////

extern int uc_register_descriptor(u8 *desc);
extern int uc_unregister_descriptor(u8 *desc);


#endif /* uc_h */
                 DSPLinux USB Client Core Driver Specification
                           v0.1 [EMAIL PROTECTED]

                               TABLE OF CONTENTS

  1. Specification Overview and Scope
  2. Terms and Abbreviations
     2.1 Conventions
     2.2 Definitions
  3. Interfaces
     3.1 Descriptor Registration
     3.2 Event Notification
     3.3 Data Flow
  4. Buffer Flow
  5. Contexts (Threads)
     5.1 Interrupt
     5.2 Tasklet
     5.3 User/Kernel Thread
  6. Module Parameters
  Appendix A: Isochronous Transfers

1. Specification Overview and Scope

I'll assume that you're familiar with the following:

  o  USB 1.0 and 1.1 Specifications

This specification covers RidgeRun's DSPLinux USB Client Core Driver. I will
refer to this simply as "the driver" in the rest of this document. If other
drivers are referenced I will unambiguously specify them.


2. Terms and Abbreviations


2.1 Conventions

Decimal numbers are not annotated. For example: 0, 1, 2.
Hex numbers are followed by an h. For example: 0h, afh, deadbeefh.
Binary numbers are followed by a b. For example: 011b

Coding standards will follow the guidelines established in
linux/Documentation/CodingStyle.


2.2 Definitions

CCD     See client class driver.

client class driver (CCD)
        A kernel driver on the device that implements a USB class. Sometimes
        the USB spec refers to a "device function" -- this is another way to
        think of client class drivers.

configured
        When the host selects the driver configuration to be the current active
        configuration for the device then I say the driver is configured.

descriptor chain
        A configuration descriptor followed by its associated interface and
        endpoint desciptors as described in Chapter 9 if the USB spec.

DSPLinux 
        RidgeRun's Linux distribution, tailored for system-on-chip platforms
        which integrate a DSP and a GPP into the same silicon core.

DSPLinux USB Client Core Driver (UC) 
        The platform-specific driver which encapsulates hardware details and
        provides a framework for class drivers to operate.

host class driver
        A driver in the host OS that communicates with a particular device
        function.

packet  A single USB packet. The driver uses a packet header of type uc_pkt_t
        and a flat buffer to handle packets.

transaction
        A USB transaction, which consists of a sequence of packets. Given a
        sequence of packets, you can determine the end of the transaction in
        one of three ways:
        a) A short or zero-length packet will always be the last packet in a
           transaction
        b) Unfortunately, a zero-length packet is not *required* to mark the
           end of a transaction (this applies to cases where all the bytes in a
           transaction evenly divide into the packet size). In this case the
           only way to determine the end is via an upper-layer protocol.

uc_     USB Client. Used as a prefix for all the functions in the public API
        exported by the DSPLinux USB Client core driver.


3. Interfaces


3.1 Descriptor registration

3.1.1 uc_register_descriptor

    extern int uc_register_descriptor(u8 *desc);

Use this to register a descriptor chain or a string descriptor. Once registered
the host will be able to find it during enumeration.

desc - this is a raw byte buffer containing the descriptor chain or string
descriptor. The UC driver will keep a pointer to the buffer, IT WILL NOT MAKE A
COPY. The UC driver determines which configuration the chain is for by checking
the bConfigurationValue in the configuration descriptor at the head of the
chain. This value should not exceed the bNumConfigurations parameter of the UC
driver (see the section on module parameters below). When the host requests the
configuraton descriptor, the UC driver will send it verbatim. It's on the
caller to make sure the chain is properly formatted with respect to descriptor
order, consistency and endianness. Note that the endpoint descriptors are
necessarily platform-specific.

Note: to support string descriptors one of the CCDs must register string
descriptor 0, specifying the languages for the device. By default the UC driver
does not assume support for any string descriptors so it does not have one
built-in.

Returns:
o  >= 0 on success. For descriptor chains this is the configuration number (and
   will match the bConfiguration value in the chain), for string descriptors
   this is the string index (which can then be used to fill out the pertinent
   fields in the descriptor chain before submitting *it*).
o  -ENXIO if the configuration number is out of range. The configuration number
   comes from the bConfigurationValue field of the Configuration Descriptor at
   the head of the chain (byte 5), and is compared to the bNumConfigurations
   parameter of the UC driver.
o  -EINVAL if the descriptor type (byte 1) is not CONFIGURATION (2) or STRING
   (3).


3.1.2 uc_unregister_descriptor

    extern int uc_unregister_descriptor(u8 *desc);

Although I do not recommend writing client class drivers that can be removed at
runtime, it might prove useful during development of CCD's. You can call this
to remove a descriptor when you unload your driver.


3.2 Event notification

If your driver needs to handle vendor or class-specific device requests then it
will need to be notified when the UC driver receives them. If it implements a
class then it needs to be notified when the host selects its configuration. To
receive these events it must register a callback interface with the UC driver.


3.2.1 Filter Bits

Use these in the filter field of the uc_notifier struct. A set bit means you
want to receive the associated event.


3.2.1.1 UCE_CLASS_REQ

Set this bit to receive notification of class-specific device requests when
your configuration is selected by the host. The data argument to the
notification callback will contain the eight-byte Device Request from the host
in raw form. If your driver receives this event then it is responsible for
responding to it. See Responding to Device Requests below.


3.2.1.2 UCE_VENDOR_REQ

Set this bit to receive notification of vendor-specific device requests. The
data argument to the notification callback will contain the eight-byte Device
Request from the host in raw form. If your driver receives this event then it
is responsible for responding to it. See Responding to Device Requests below.


3.2.1.2 UCE_CFG_CHANGE

Set this bit to receive notification when the host sends a SetConfiguration
device request. The data argument to the notification callback will contain the
new configuration. Although it's not necessary for your driver to do anything
when it gets this event, if the new configuration matches your drivers it
might take the opportunity to prepare for host communications (e.g., submitting
read packets on the IN endpoints) before returning.

Note that for this particular event, the callback runs in an interrupt
context. I hate to do this but the only way I see to avoid race condition hell
is to strictly serialize configuration change notices. So your callback
function must obey all the rules of running in an ISR: no blocking, take as
little time as possible, etc.


3.2.2 Notifier Struct

    typedef void (*uc_notify_cb_t)(struct uc_notifier *notifier, u8 event, 
                                   void *data);

    typedef struct uc_notifier {
            struct list_head list;
            uc_notify_cb_t cb;
            u8 filter;
            u8 cfg;
    } uc_notifier_t;

This is what your driver registers to receive events.


3.2.2.1 list

This field is used by the UC driver. Your driver shoud leave it alone.


3.2.2.2 cb

This is your driver's callback routine. It can be called in IRQ and tasklet
contexts, so it MUST NEVER BLOCK.


3.2.2.3 filter

This is the filter bitmap indicating which events your driver wants to be
notified about. A set bit means it wants notification.


3.2.2.4 cfg

This is the configuration in which your driver is active. If and only if you
set the UCE_CLASS_REQ bit in the filter then this field is required. This
gaurantees that you will only receive Class Device Requests when the host has
selected your driver's configuration.

3.2.3 uc_register_notifier

    void uc_register_notifier(uc_notifier_t *notifier);

Call this when your driver loads if you want to receive events.


3.2.4 uc_unregister_notifier

    void uc_unregister_notifier(uc_notifier_t *notifier);

Call this to stop receiving events. I've included this to make debugging CCDs
easier.


3.2.4 Responding to Device Requests

When you set the UCE_CLASS_REQ or UCE_VENDOR_REQ flags in the notification
filter then the UC driver will notify you when it gets the pertinent Device
Request. Here's the basic algorithm which your notifier should follow when it
determines that this is a Device Request event:

        notification_callback() {
                decode_request
                if request is not supported {
                        call uc_halt
                }
                else if request is a control read {
                        call uc_tx
                }
                else {
                        call uc_rx
                }
        }

In the case of control reads or writes, the UC driver will invoke the packet
callbacks when the transaction is complete. On the callbacks your driver is
responsible for completing the STATUS stage of the control transfer. You have
the option of STALLing the control endpoint (by calling uc_halt) or of
submitting a zero length packet for reading (in the case of control reads) or
writing (in the case of control writes).


3.3 Data Flow

The basic model is:
1. CCD submits a buffer for reading/writing on an endpoint
2. UC driver handles the transfer via hardware
3. UC driver invokes a callback to tell the CCD the buffer is done

On transmit, the UC driver sends a buffer as a single USB transaction (possibly
split over multiple USB packets).

On receive, the UC driver fills the buffer with at most one USB transaction. If
 the transaction will not fit in the buffer the UC driver discards the leftover
 bits and sets a flag to warn the CCD of the overflow.

The model is asynchronous because some CCDs may run entirely in an IRQ or
tasklet context, so blocking would not be an option.

The model is based on USB transactions instead of USB packets in order to make
better use of DMA.

The model relies on the CCD to provide read buffers becase a) the CCD drivers
protocol *should* tell it how big the next incoming transaction is (the UC
driver has no way of knowing) and b) this allows the CCD to drive USB flow
control, reducing upper layer protocol races and c) buffering in the UC driver
leads to messy cleanup issues I don't want to deal with.


3.3.1 Packet Structure

    typedef void (*uc_pkt_cb_t)(struct uc_pkt *pkt);

    typedef struct uc_pkt {

            struct list_head list; // used by core
            uc_pkt_cb_t cb;        // called by core when done
            void *private;         // owner's optional data (untouched by core)
    
            u8 *data;   // data pointer (set by owner)
            u8 *ptr;    // pointer to next byte to send/receive
            u16 len;    // max length of data buffer (set by owner)
            u16 n;      // actual length of data in buffer
    
            u16 flags;  // flags (set by core)
            u16 frame;  // SOF frame # (depends)
            u8  ep;     // endpoint # (set by owner)
            u8  cfg;    // configuration # (set by owner)
    
    } uc_pkt_t;


The figures below show some suggested of the uc_pkt_t with data buffers.


        Figure 3.1 - uc_pkt_t Struct Prepended to Data Buffer

                             =====================
                           / |///////////////////|
                 uc_pkt_t |  | data       |      ---+
                          |  | ptr        |      -- |-+
                           \ |///////////////////|  | |
                          ---+-------------------+<-+ |
                           | |///////////////////|    |
                           | +-------------------+<---+                        
                           | |      payload      |
                           | |     (n bytes)     |
                             |                   |
                         len +-------------------+
                             |///////////////////|
                           | |///////////////////|
                           | |///// unused //////|
                           | |///////////////////|
                           | |///////////////////|
                          ---=====================


            Figure 7.4 - uc_pkt_t Struct with External Data Buffer

                    =====================
                  / |///////////////////|
         header  |  | data       |      ---->=====================---
                 |  | ptr        |      --+  |///////////////////| |
                  \ |///////////////////| |  |///////////////////| |
                    +-------------------+ +->+-------------------+ |
                                             |                   | |
                                             |                   | |
                                             |                   | |
                                             |                   | |
                                             |                   | |
                                             |      payload      |
                                             |     (n bytes)     | len
                                             |                   |
                                             |                   | |
                                             |                   | |
                                             |                   | |
                                             |                   | |
                                             /                   / /

                                             /                   / /
                                             |                   | |
                                             =====================---


3.3.1.1 list

This field is used by the UC driver. If a buffer is not owned by the UC driver
(it has not been submitted or has been returned via a callback) then the CCD
can use this to keep lists of available buffers. See linux/list.h for some
helpful routines.


3.3.1.2 cb

The UC driver calls this to return a buffer to its owner. It runs in a tasklet
context, so NO BLOCKING.


3.3.1.3 private

This field belongs to the CCD to do with as it pleases. The UC driver doesn't
touch it.


3.3.1.4 data

This is a pointer to the start of the data buffer.


3.3.1.5 ptr

For transmit buffers, this points to the next byte of data to send. For receive
buffers, this points to the next empty byte to receive into.


3.3.1.6 len

This is the *actual* length of the buffer -- NOT the amount of data it
contains.

3.3.1.7 n

This is the amount of data in the buffer.


3.3.1.8 flags

These are status flags set by the UC driver before it returns a
packet. Caller's should make sure these flags are clear before submitting a
buffer - I don't gaurantee that the UC driver will clear them when it receives
a new buffer.


3.3.1.9 frame

USB frame number. Relevant only to INTR and ISO transfers.

For transmit buffers bound for INTR or ISO endpoints, iff the UCF_SYNCH_FRAME
flag is set then the UC driver will hold off on sending these buffers until the
designated frame begins. Note that the UC driver always appends buffers to the
queue, and it does not skip buffers when transmitting. So if you submit a
UCF_SYNCH_FRAME buffer and then submit a non-synched buffer, the non-synched
buffer will not go out until after the synched buffer. (Note that USB frame
numbers roll over at 4095, or about every 4 seconds).

For buffers received on an ISO endpoint, the frame number the buffer was
received on is recorded by the UC driver before invoking the callback.


3.3.1.10 ep

This is the endpoint this buffer should send to/receive from. It's on the
caller to make sure this is valid for the existing hardware. The UC driver
makes only minimal checks on the sanity of this value.


3.3.1.11 cfg

This is the configuration the endpoint is in. If this does not match the
current active configuration (as selected by the host) then the UC driver will
reject submission of this packet.


3.3.2 Buffer Flags

These bits are used in the flags field of the uc_pkt_t struct.

3.3.2.1 UCF_EOT

End-of-transaction flag. For received buffers, this means that a complete
transaction was received into the buffer. This is the normal case.


3.3.2.2 UCF_ABORT

The transfer was aborted. This can occur if anything happens to change the
device's configuration before the transfer can complete (e.g., cable unplug or
SetConfiguration request).


3.3.2.3 UCF_OVERRUN

Receive buffer overrun. This can occur if the host sends more data in a
transacton than will fit in the buffer. The UC driver detects this condition
when the hardware FIFOs contain more data than is available in the buffer.

Note: the UC driver detects an overrun when it finds more data in the h/w fifo
than will fit in the buffer. In this case it will discard the leftover data in
the h/w fifo. A good way to prevent losing this data is to submit receive
buffers which are a multiple of the endpoint's wMaxPacketSize. This way it will
never receive more data than it has buffers for.

Note: if the receive buffer is a multiple of the wMaxPacketSize, and the host
sends one packet too many, then the UC driver will not detect this as an
overrun. It will treat the extra packet as the first packet in the next
transaction, instead of the last packet of the last transaction. Because the
USB spec does not *require* transactions to terminate in a short or zero-length
packet the UC driver cannot reliably determine end-of-transaction
boundaries. The CCD can detect when this occurs if it receives a full buffer
with neither the UCF_EOT nor UCF_OVERRUN flags set.

3.3.3 uc_tx 

    int uc_tx(uc_pkt_t *pkt);

Submit a buffer for transmission. 'pkt' must be setup with the appropriate cfg,
ep, cb, etc. The buffer will be queued behind any other buffers submitted for
that endpoint. The UC driver will return the buffer via the pkt->cb function
when it is done with it.

If all the data is successfully sent and the host ACKs it the UC driver returns
the buffer with all flags clear.

If an event occurs which prevents all the data from being sent (e.g. unplug,
SetConfiguration device request, etc) then the UC driver returns the buffer
with the UCF_ABORT flag set.

Returns:
o  0 if it queued the packet for transmission
o  -EPERM if pkt->cgf is not the current active configuration
o  -EINVAL if pkt->ep is not a possible endpoint number.


3.3.4 uc_rx

    int uc_rx(uc_pkt_t *pkt)

Submit a buffer for receiving data from the specified endpoint. The UC driver
queues the buffer behind any other buffers previously submitted for this
endpoint. The UC driver will fill up to pkt->len bytes until the USB
transaction is done, and then return the buffer via the pkt->cb function.

If a complete transaction is received into the buffer then the UC driver sets
the UCF_EOT flag before returning the buffer.

If the buffer could not hold all the data in the transaction then the UC driver
sets the UCF_OVERRUN flag before returning the buffer, and discards the rest of
the data for the transaction. It does *not* fetch another buffer and begin
filling it with the remaining data (it assumes overruns represent an upper
layer protocol error that will be handled by the CCD).

Returns:
o  0 if it queued the packet for transmission
o  -EPERM if pkt->cgf is not the current active configuration
o  -EINVAL if pkt->ep is not a possible endpoint number.


3.3.5 uc_halt

    void uc_halt(u8 cfg, u8 ep)

Halt an endpoint. This allows the CCD to force a functional STALL of an
endpoint (usually done to inform the host it detected a protocol error and some
kind of recovery is needed).

If 'cfg' does not match the current active configuration then this does
nothing.


3.3.6 uc_clear_halt

    void uc_clear_halt(u8 cfg, u8 ep)

Undo a halt, restoring an endpoint to operation. Usually the CCD does this
after receiving a Class-specific Device Request to clear up the protocol error
that caused the halt.

If 'cfg' does not match the current active configuration then this does
nothing.


3.3.7 uc_flush

    void uc_flush(u8 cfg, u8 ep)

Forcibly remove all buffers queued for the endpoint, causing them to be
returned via their callbacks. CCDs might do this if they receive a
protocol-level reset or (during debug) before being unloaded by rmmod.

Note: CCDs do not need to call this if the host unselects their
configuration (e.g., unplug, SetConfiguration, etc). In these cases the UC
driver automatically returns all buffers for all endpoint on the dead configuration.


3.3.8 uc_get_frame

    u16 uc_get_frame(void)

Returns the current USB frame number. This is to help drivers that need to
synchronize with the USB SOF's.

3.3.8 uc_wait_frame

    int uc_wait_frame(u16 frame)

Blocks the caller until the designated SOF occurs. Since this is a blocking
call it should never be called within an interrupt or tasklet context. That
rules out all the callback routines for event notification or buffer
return. For this reason drivers that need to synchronize with the bus will
probably need a user context or a kernel daemon.

Returns:
o  0 on success
o  -EINVAL if the frame number is invalid
o  -ERESTARTSYS if the process received a signal while blocked
o  -EPERM if called from an interrupt context


4. Buffer Flow


4.1 Data Buffers

The UC driver keeps no data buffers of its own. All data buffers are provided
via the uc_tx and uc_rx calls.

                              Fig 4.1 Buffer Flow

                              /-----------------\
                    +---------| CCD buffer pool |<-----+
                    |         \-----------------/      |
                    |                .                 |
                    V                .                 |
           +---------------+    +----------+       +---------+   Upper layer(s)
===========| uc_tx / uc_rx |====| uc_flush |=======| pkt->cb |================
           +---------------+    +----------+       +---------+       UC driver
                    |                .                 |
                    |                .                 |
                    |   /----------------------------\ |
                    +-->| UC driver endpoint queues  |-+
                        \----------------------------/


Figure 4.1 shows the buffer flow model. The CCD buffer pool is just one
possible solution -- once a buffer is above the dividing line the UC driver
doesn't care what happens to it.

Events which cause a buffer to be returned include:
o  Data sent and ACK'd (tx buf)
o  Buffer full (rx buf)
o  USB transaction received (rx buf)
o  Configuration change (all)
o  uc_flush (all for the specific endpoint)

No special allocation/deallocation routines are provided. This is on the CCD's
to handle however they please.

Note: NEVER DEALLOCATE BUFFERS OWNED BY THE UC DRIVER.
Note: NEVER ALLOW A CCD DRIVER TO BE UNLOADED WHILE THE UC DRIVER OWNS BUFFERS
WITH CALLBACKS INTO THE MODULE.

Because of that second note, and because it doesn't really make sense for a
device to change what it "is" at runtime, I strongly discourage you from even
allowing your CCD's to be dynamically unloadable at release time. To ensure
this never happens you can use the MOD_INC_USE_COUNT macro to tell the kernel
that the module is always in use and can't be unloaded. That being said, I've
tried to add some support to allow you to remove modules while they're in the
debug phase. It's on you to avoid race conditions with respect to note 2. I
also recommend you always unplug the USB cable before unloading modules, and
reloading them before pluggin back in.


4.2 Device Request Buffer

The UC driver keeps one eight-byte buffer for receiving Device Requests. It
will pass this buffer to an upper layer as the data argument to the notificaton
callback when processing non-standard device requests.

If an upper layer receives this call it can assume that the UC driver retains
ownership of the buffer. It should not modify the buffer or try to deallocate
it.


5. Contexts (Threads)

The UC driver involves two different execution contexts: interrupt and
tasklet. Some CCD's will no doubt add others like user, kernel thread or
timer contexts.

None of the calls in the UC driver API are blocking, and all are reentrant and
safe to call from any context.


5.1 Interrupt

The interrupt context is largely constrained to the UC driver itself. However,
some CCD event callbacks may be run in this context. Specifically, the
UCE_CONFIG_CHANGE event must run in this context to properly serialize
configuration change events and prevent race conditions.

For this reason the event callbacks must *NEVER* perform blocking operations,
and should execute as quickly as possible.


5.2 Tasklet

All other CCD callbacks are run in a tasklet context. A tasklet can only be
preempted by a hardware interrupt, so BLOCKING OPERATIONS ARE FORBIDDEN. But
since they do not affect interrupt latency they are not as time-critical as
code running in an interrupt context.

NOTE: *** Warning ***
ALL CALLBACKS ARE EXPRESSLY FORBIDDEN TO PERFORM ANY BLOCKING OPERATIONS.


5.3 User/kernel thread

Currently the UC driver does not itself employ any helper daemons or
threads. Most CCDs no doubt will. All calls into the API are safe and
reentrant for these contexts.


6. Module Parameters

The UC driver is specific to the platform (OMAP1510) but not to the OEM
application. Since it will be shipped as a binary, and OEM's will need to add
their own CCD support on an ad-hoc basis, I've exported some module parameters
which can be set as necessary when the module is loaded.

These parameters can be specified at load time either as arguments to insmod or
modprobe. In the case of modprobe they can alternatively be specified in a
configuration file. By default modprobe uses /etc/modules.conf as its config
gile, but the -C or --config option can override this. See man (8) modprobe.

All of the currently supported parameters are fields in the device
descriptor.


6.1 bcdUSB

A field in the Device Descriptor. Defaults to 0x0101 (1.1).


6.1 bDeviceClass

A field in the Device Descriptor. Defaults to 0.


6.1 bDeviceSubClass

A field in the Device Descriptor. Defaults to 0.


6.1 bDeviceProtocol

A field in the Device Descriptor. Defaults to 0.


6.1 bMaxPacketSize

A field in the Device Descriptor. Defaults to 64. This is hardware-specific,
and there's really no good reason to ever change from the default. Note that
this applies only to endpoint 0 (the other endpoints are specified in their
descriptors).


6.1 idVendor

A field in the Device Descriptor. Defaults to 0xc01d. OEMs should definitely
override the default to use their own USB org-assigned code.


6.1 idProduct

A field in the Device Descriptor. Defaults to 0xbee3. OEMs should definitely
override the default to use their own product code.


6.1 bcdDevice

A field in the Device Descriptor. Defaults to 0x0009 (don't ask). OEMs will
want to override this to reflect the unit id.


6.1 bNumConfigurations

A field in the Device Descriptor. Defaults to 1. Override this if you want to
support multiple configurations.


Appendix A: Isochronous Transfers

Consider an ISO IN example. Let's say that your driver queues a 512-byte buffer
on an ISO endpoint by calling uc_tx. The UC driver queues up bMaxPacketSize
bytes in the hardware every USB frame. So, if bMaxPacketSize if 64, all the
data will be sent after 8 USB frames and then the UC driver will invoke the
buffer callback.

Now consider an ISO out example. Let's say your driver queues a 512 byte buffer
to receive ISO data into. The UC driver will fill it with the ISO data for one
frame (bMaxPacketSize), set the 'frame' field to indicate which USB frame the
data was received in, and invoke the callback. It won't try to fill the whole
buffer.

Some USB specs (like the Audio Class Spec) require a device to gaurantee it
will do things like  play an audio sample no sooner or later than x ms after
receving it. This is necessary to support features like 3D sound where the
phase information between different audio channels is important.

To support this I've added the uc_get_frame() function to the API. Driver's
which need to synchronize using USB framing information can poll this
function. I've also added the uc_wait_frame() function to allow a process to
block until a frame occurs.

Reply via email to