USBFS(2)                                                 USBFS(2)

          usbreadbuf, usbfsadd, usbfsdel, usbdirread, usbfsinit,
          usbdirfs, usbfs - USB device driver file system library

          #include <u.h>
          #include <libc.h>
          #include <thread.h>
          #include "../lib/usb.h"
          #include "../lib/usbfs.h"
          enum {
                  Hdrsize = 128,          /* plenty of room for headers */
                  Msgsize = 8 * 1024,
                  Bufsize = Hdrsize + Msgsize,
                  Namesz = 40,
                  Errmax = 128,
                  ONONE = ~0,             /* omode in Fid when not open */
          struct Fid {
                  int     fid;
                  Qid     qid;
                  int     omode;
                  Fid*    next;
                  void*   aux;
          struct Usbfs {
                  char    name[Namesz];
                  uvlong  qid;
                  Dev*    dev;
                  void*   aux;
                  int     (*walk)(Usbfs *fs, Fid *f, char *name);
                  void    (*clone)(Usbfs *fs, Fid *of, Fid *nf);
                  void    (*clunk)(Usbfs *fs, Fid *f);
                  int     (*open)(Usbfs *fs, Fid *f, int mode);
                  long    (*read)(Usbfs *fs, Fid *f,
                                  void *data, long count, vlong offset);
                  long    (*write)(Usbfs *fs, Fid*f,
                                  void *data, long count, vlong offset);
                  int     (*stat)(Usbfs *fs, Qid q, Dir *d);
                  void    (*end)(Usbfs *fs);
          typedef int (*Dirgen)(Usbfs*, Qid, int, Dir*, void*);
          long    usbreadbuf(void *data, long count,
                          vlong offset, void *buf, long n);
          void    usbfsadd(Usbfs *dfs);
          void    usbfsdel(Usbfs *dfs);
          int     usbdirread(Usbfs*f, Qid q, char *data, long cnt,
                          vlong off, Dirgen gen, void *arg);
          void    usbfsinit(char* srv, char *mnt, Usbfs *f, int flag);
          void    usbfsdirdump(void);

     USBFS(2)                                                 USBFS(2)

          extern char Enotfound[], Etoosmall[], Eio[], Eperm[], Ebadcall[],
                  Ebadfid[], Einuse[], Eisopen[], Ebadctl[];
          extern Usbfs usbdirfs;
          extern int usbfsdebug;

          This library provides an alternative to 9p(2) for implement-
          ing a file server within a USB driver.  Drivers using this
          library may be embedded into usbd(4). It may be also desir-
          able to use this library when drivers are not embedded
          because it is tailored to work well with the library for
          handling USB devices.

          A USB file system is described by a Usbfs structure.  In
          most cases, the driver is not responsible for the root of
          the file tree.  It is customary that a driver creates a file
          server for each device handled and links all of them to a
          root directory implemented by the usbdirfs file system
          implemented by the library.  This root directory is bound to
          /dev in most cases.

          Usbdirfs implements a root directory populated by named file
          trees, each one described by a Usbfs structure.

          The field contains the name for the root direc-
          tory of the file system, usually a directory seen at
          /dev/name when the driver is embedded.

          Usbfs.qid maintains a value used to decorate qids for the
          file tree.  This may be ignored when usbdirfs is not used.
          Otherwise, usbdirfs assigns a unique value kept at the high
          32 bits of Qid.path for all files on each file tree bound to
          it.  Each Usbfs server must bitwise OR Usbfs.qid to all
          Qid.path values returned by its functions.  In the same way,
          functions usually clear bits in Usbfs.qid before processing
          Qid.path values supplied as input.

          The USB device handled by a file tree is referenced from
 (and a reference must be counted for it).  This
          permits the following functions to quickly locate the device
          of interest, and also permits releasing the device when no
          request is outstanding.

          The field Usbfs.aux is for the device to use.  The rest of
          the fields implement the 9P protocol for the device.  Not
          all the operations need be implemented.  Only walk, open,
          read, write, and stat, must be implemented (and their corre-
          sponding fields in Usbfs may never be nil).  These functions
          must return -1 upon failure and set the error string to
          reflect the cause of a failure.

          In all the functions, a 9P fid is represented by a Fid

     USBFS(2)                                                 USBFS(2)

          structure.  It contains the 9P fid, the corresponding qid,
          and an auxiliary pointer for the driver to use.  Open fids
          have a valid open mode in omode while others have ONONE to
          indicate that the fid is not open.  The library takes care
          of which fids exist and which ones do not.

          Walk must walk f to name (a single name, not a file path) in
          the supplied fs. Its implementation should update the qid in
          f to reflect the walk.  This function must bitwise OR any
          returned Qid with Usbfs.qid , if usbdirfs is used.

          Clone must clone fid of onto nf so that, upon successful
          completion, nf also refers to the file that f refers to.  An
          implementation must update the Qid of the cloned fid.  If
          this function is not supplied, the library copies the aux
          field to the cloned fid.

          Clunk clunks f. It usually releases data kept in the aux
          field, but may be set to nil otherwise.

          Open prepares the fid f for I/O according to mode. The open
          mode in the fid is updated by the library upon return.  The
          library checks trivial cases like opening already-open fids.
          The implementation performs most permission checking.

          Read reads up to count bytes into data starting at offset in
          the file referenced by f. Write is the counterpart.  To read
          from directories, the function usbdirread may be called.  It
          returns the return value of read or -1.  usbdirread calls
          gen to iterate through files as needed.  The Dirgen function
          will be called with index values of 0 and up to ask for the
          first file and following files.  To read from data already
          in buffers, the function usbreadbuf may help.  It must be
          given the arguments supplied by the user, plus the buffer
          and buffer size.

          Stat must fill d with the directory entry for the file iden-
          tified by q. As an aid, d is initialized to fake access and
          modification times, and user and group ids.  Also, the field
          name in d is initialized to point to a 40-byte buffer.  If
          the file name fits, it may be copied directly into d->name
          without allocating memory for that purpose.  Otherwise
          d->name must be initialized to point to static memory.

          The function end is called upon termination of the file tree
          to release resources.

          Calling usbfsinit starts a file server for f that mounts
          itself at mnt and posts srv at srv(3). In most cases, the
          file system supplied is usbdirfs. The flag is used for
          mount(2). Once usbdirfs is started, calls to usbfsadd add a
          file tree implemented by dfs to the root directory of

     USBFS(2)                                                 USBFS(2)

          usbdirfs and calls to usbfsdel remove that binding (and
          release resources including the reference to the USB

          Various error strings are declared as an aid.  The global
          usbfsdebug may be set to trigger diagnostics and protocol

          See /sys/src/cmd/usb/disk for an example driver that uses
          this library.  Looking at an example is strongly suggested
          to see how reference counts for the USB device and the file
          system are handled.


          usb(2), usb(3), usb(4), usbd(4).

          Not heavily exercised yet.