ugen(7D)




NAME

     ugen - USB generic driver


SYNOPSIS

     Node Name@unit-address

     #include <sys/usb/clients/ugen/usb_ugen.h>


DESCRIPTION

     ugen is a generic USBA (Solaris USB Architecture)  compliant
     client  character driver that presents USB devices to appli-
     cations through the  standard  open(2),  close(2),  read(2),
     write(2),  aioread(3AIO),  aiowrite(3AIO)  Unix  system call
     interface. Uninterpreted raw data  are  transferred  to  and
     from  the  device  via file descriptors created for each USB
     endpoint. Status is obtained  by  reading  file  descriptors
     created for endpoint and full device status.

     ugen supports control, bulk,  and  interrupt  (in  and  out)
     transfers. Isochronous transfers are not supported.


BINDING

     ugen can bind to a device with one or more interfaces in its
     entirety, or to a single interface of that device. The bind-
     ing  type  depends  on  information  that   is   passed   to
     update_drv(1M).  update_drv(1M)  adds  an  additional device
     type to the list  of  device  types  being  managed  by  the
     driver.

     Names used to bind drivers to the entire device, as well  as
     those  used  for binding to just one interface, are shown in
     the output of the prtconf -v command. A list  of  names  for
     each device is shown in the ouput as that device's "compati-
     ble" property.  Each name in the list is called a  "compati-
     ble"  name.  Be  sure the device is powered on and connected
     before you issue prtconf -v.

     prtconf entries for most devices  with  multiple  interfaces
     have "usb,device" as their last compatible name. Their "com-
     patible" property is similar to:

     name='compatible' type=string items=5
       value='usb472,b0b0.100.config1' + 'usb472,b0b0.100' +
       'usb472,b0b0.1' + 'usb472,b0b0' + 'usb,device'

     Names are listed from most specific to most general, and the
     system  searches them in that order. Specify any name listed
     before "usb,device" to  bind  the  entire  device  to  ugen.
     "usb,device" must not be used.  If the system finds no other
     matching name first, "usb,device" binds the full  device  to
     usb_mid(7D).  usb_mid  then  creates a child for each inter-
     face, enabling different drivers  to  bind  to  each  child.
     Each child will then have its own "compatible" property with
     a list of names.  All compatible names of interface children
     begin with "usbif." For example:

     name='compatible' type=string items=2
       value='usbif472,b0b0.100.config1.0' + 'usbif472,b0b0.config1.0'

     If the device has just one configuration and one  interface,
     and is of device class 0, no default "usb,device" compatible
     name is added; instead a list of "usbif" compatible names is
     appended. For example:

     name='compatible' type=string items=8
       value='usb430,100.105' + 'usb430,100' + 'usbif430,class3.1.2' +
       'usbif430,class3.1' + 'usbif430,class3' + 'usbif,class3.1.2' +
       'usbif,class3.1' + 'usbif,class3'

     When using ugen for the first time, you must add the  driver
     utilizing add_drv, using a command of the following form:

     add_drv -m '* <device perms> <owner> <group>'
      -i '"<new device type>"' usba10_ugen

     If the command fails with:

     (usba10_ugen) already in use as a driver or alias.

     ...then add the device using update_drv (below).

     To bind the new device type while  keeping  existing  device
     types, issue an update_drv(1M) command of the following form
     (on a single line):

     update_drv -a -m '* <device perms> <owner> <group>'
         -i '"<new device type>"' usba10_ugen

     An example showing how to bind an  entire  composite  device
     follows:

     update_drv -a -m '* 0666 root sys' -i '"usb472,b0b0"'  usba10_ugen

     Compatible names representing single interfaces of composite
     devices are of the following form:

     "usbif<vid>,<pid>.config<cfg value>.<interface number>"

     An example showing how to bind a child  device  representing
     interface  0  of  configuration 1 of a composite device fol-
     lows:

     update_drv -a -m '* 0666 root sys'
         -i '"usbif472,b0b0.config1.0"' usba10_ugen

     You can also use update_drv to remove bindings.  Please  see
     update_drv(1M) for more information.

     Note that ugen driver device-bindings are  preserved  across
     operating system upgrades.


LOGICAL DEVICE NAME FORMAT

     For each device or child device it manages, ugen creates one
     logical device name for device-wide status, one logical dev-
     ice name for endpoint 0 and one for its  status.  ugen  also
     creates  logical device names for all other endpoints within
     the device node's binding scope (interface or device),  plus
     logical device names for their status.

     If separate ugen instances control different  interfaces  of
     the same device, the device-wide status and endpoint logical
     device names created for each instance will share access  to
     the  same  source  or  endpoint pipes. For example, a device
     with  two  interfaces,  each  operated  by  their  own  ugen
     instance,  will  show  endpoint0  as  if0cntrl0 to the first
     interface, and will show  it  as  if1cntrl0  to  the  second
     interface.  Both  of  these  logical device names share end-
     point0.  Likewise  for  the  same  device,  ugen  makes  the
     device-wide   status  available  as  if0devstat to the first
     interface  and  as  if1devstat  to  the  second   interface.
     if0devstat and if1devstat both return the same data.

     Any ugen logical device name can be held open  by  only  one
     user at a time, regardless of whether the O_EXCL flag passed
     to open(2). When a single pipe or data source is  shared  by
     multiple  logical  device  names,  such  as if[0,1]cntrl0 or
     if[0,1]devstat above, more  than  one  logical  device  name
     sharing  the pipe or data source can be open at a time. How-
     ever, only one user may  access  the  shared  pipe  or  data
     source at a time, regardless of the logical device name used
     for access.

     When ugen is bound to an entire device, the following  logi-
     cal  device  names  are  created  (each on a single line). N
     represents the instance number of the device type.

     Endpoint 0 (default endpoint):

             /dev/usb/<vid>.<pid>/<N>/cntrl0
             /dev/usb/<vid>.<pid>/<N>/cntrl0stat

         For example:

             /dev/usb/472.b0b0/0/cntrl0
             /dev/usb/472.b0b0/0/cntrl0stat

     Configuration 1, Endpoints > 0, alternate 0:
             /dev/usb/<vid>.<pid>/<N>/if<interface#>
                                     <in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/if<interface#>
                                     <in|out|cntrl><endpoint#>stat

         For example:

             /dev/usb/472.b0b0/0/if0in1
             /dev/usb/472.b0b0/0/if0in1stat

     Configuration 1, Endpoints > 0, alternate > 0:

             /dev/usb/<vid>.<pid>/<N>/if<interface#>.
                                     <alternate><in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/if<interface#>.
                                     <alternate><in|out|cntrl><endpoint#>stat

         For example:

             /dev/usb/472.b0b0/0/if0.1in3
             /dev/usb/472.b0b0/0/if0.1in3stat

     Configuration > 1, Endpoints > 0, alternate 0:

             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>
                                     <in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>
                                     <in|out|cntrl><endpoint#>stat

         For example:

            /dev/usb/472.b0b0/0/cfg2if0in1
            /dev/usb/472.b0b0/0/cfg2if0in1stat

     Configuration > 1, Endpoints > 0, alternate > 0:
             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>.
                                     <alternate<in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>.
                                     <alternate<in|out|cntrl><endpoint#>stat

         For example:

             /dev/usb/472.b0b0/0/cfg2if0.1in1
             /dev/usb/472.b0b0/0/cfg2if0.1in1stat

       Device status:

             /dev/usb/<vid>.<pid>/<N>/devstat

         For example:

             /dev/usb/472.b0b0/0/devstat

     When ugen is bound to a single device interface, the follow-
     ing logical device nodes are created:

     Endpoint 0 (default endpoint):

              /dev/usb/<vid>.<pid>/<N>/if<interface#>cntrl0
              /dev/usb/<vid>.<pid>/<N>/if<interface#>cntrl0stat

         For example:
             /dev/usb/472.b0b0/0/if0cntrl0
             /dev/usb/472.b0b0/0/if0cntrl0stat

     Device status:
             /dev/usb/<vid>.<pid>/<N>/if<interface#>devstat

         For example:
              /dev/usb/472.b0b0/0/if0devstat

     The format for all other logical device names  is  identical
     to the format used when ugen is bound to the entire device.

     Opening the endpoint of a different  configuration  or  dif-
     ferent  alternate interface will cause an implicit change of
     configuration or a switch to an alternate interface. A  con-
     figuration  change  is prohibited when any non-zero endpoint
     device nodes are open.  An  alternate  interface  switch  is
     prohibited if any endpoint in the same interface is open.


HOT-PLUGGING

     A device may be hot-removed  at  any  time.  Following  hot-
     removal,      the      device      status     changes     to
     USB_DEV_STAT_DISCONNECTED,  the  status  of  open  endpoints
     change  to  USB_LC_STAT_DISCONNECTED  upon their access, and
     all subsequent transfer requests fail. Endpoints  are  reac-
     tivated by first reinserting the device and then closing and
     reopening all endpoints that were open when the  device  was
     disconnected.


CPR

     CPR (Checkpoint/Resume) may be initiated at any time and  is
     treated  similarly to a hot-removal. Upon successful suspend
     and resume, all subsequent  transfer  requests  fail  as  an
     indication  to the application to reinitialize. Applications
     should close and reopen all endpoints to reinstate them. All
     endpoint  and device status on Resume (before close and reo-
     pen) is USB_LC_STAT_SUSPENDED. A system  suspend  will  fail
     while ugen is performing a transfer.


DEVICE POWER MANAGEMENT


     Devices which support remote wakeup  can  be  power  managed
     when  they have no open logical device nodes. When an appli-
     cation opens the first logical device node of a device, that
     application  should assume that a reinitialization of device
     state is required.


DEVICE STATUS MANAGEMENT

     Applications can monitor device status  changes  by  reading
     the  device status from the device status logical name. When
     opened without O_NONBLOCK and O_NDELAY, all reads from  that
     file descriptor (with the exception of the initial read that
     follows the open) block until a device status change occurs.
     Calls  to read will always return immediately if opened with
     O_NONBLOCK or O_NDELAY.  Nonblocking  calls  to  read  which
     have no data to return, return no error and zero bytes read.

     Device statuses are:

          USB_DEV_STAT_ONLINE
                Device is available.

          USB_DEV_STAT_DISCONNECTED
                Device has been disconnected.

          USB_DEV_STAT_RESUMED
                Device has been resumed, however, endpoints which
                were open on suspend have not yet been closed and
                reopened.

          USB_DEV_STAT_UNAVAILABLE
                Device has been reconnected,  however,  endpoints
                which  were  open on disconnect have not yet been
                closed and reopened.

     The following code reads the device  status  device  logical
     name:

     int fd;
     int status;

     if ((fd = open("/dev/usb/472.b0b0/0/devstat",
        O_RDONLY)) < 0)      {
             /* handle error */
     }

     if (read(fd, &status, sizeof(status))  != sizeof(status)) {
             /* handle error */
     }

     switch (status) {
     case USB_DEV_STAT_DISCONNECTED:
             printf ("Terminating as device has been disconnected.\n");
             exit (0);

     case USB_DEV_STAT_RESUMED:
     case USB_DEV_STAT_UNAVAILABLE:
             /*
              * Close and reopen endpoints to reestablish device access,
              * then reset device.
              */
             break;

     case USB_DEV_STAT_ONLINE:
     default:
             break;
     }

     Use poll(2) to block on  several  logical  names  simultane-
     ously, including device status logical names. Poll indicates
     when reading a logical name would return data.  See  poll(2)
     for   details. Calls to read may be done whether or not they
     follow calls to poll.


ENDPOINT STATUS MANAGEMENT

     Each data endpoint has a corresponding status logical  name.
     Use  the  status  logical  name to retrieve the state of the
     data endpoint, including  detail  on  how  its  most  recent
     transfer failed. Reads of the status file descriptors always
     return immediately. See the ERRORS section for more informa-
     tion  on  endpoint  status  values.  All logical device name
     files created for  returning  status  must  be  opened  with
     O_RDONLY.

     The following  code  illustrates  reading  the  status  file
     descriptor  of an endpoint which just failed a data transfer
     in order to get more information on the failure.

     int data_xfered, status;
     int ep1_data_fd, ep1_stat_fd;
     uchar_t request[8];

     ep1_data_fd = open ("/dev/usb/472.b0b0/0/if0out1", O_WRONLY);

     if (ep1_data_fd < 0) {
             /* Handle open error. */
     }

     ep1_stat_fd = open ("/dev/usb/472.b0b0/0/if0out1stat",
         O_RDONLY);
     if (ep1_stat_fd < 0) {
             /* Handle open error. */
     }
     data_xfered = write(ep1_data_fd, request, sizeof (request));

     /* An error occured during the data transfer. */
     if (data_xfered != sizeof (request)) {

             /* Read status file descriptor for details on failure. */
             if (read(ep1_stat_fd, (int *)&status, sizeof (status)) !=
                 sizeof (status)) {
                     status = USB_LC_STAT_UNSPECIFIED_ERR;
             }

             /* Take appropriate action. */
             switch (status) {
             case USB_LC_STAT_STALL:
                     printf ("Endpoint stalled.\n");
                     break;
             case ...
                     ...
             }

        }


CONTROL TRANSFERS

     The control endpoint is typically used to set up the  device
     and to query device status or configuration.

     Applications requiring I/O on a control endpoint should open
     the  corresponding  logical device name and use regular UNIX
     I/O  system   calls.   For   example:   read(2),   write(2),
     aioread(3AIO)  and  aiowrite(3AIO). poll(2) is not supported
     on control endpoints.

     A control endpoint must be opened with O_RDWR  since  it  is
     bidirectional.  It  cannot  be  opened  with  O_NONBLOCK  or
     O_NDELAY.

     For example:

     fd = open("/dev/usb/472.b0b0/0/cntrl0", O_RDWR);

     fdstat = open("/dev/usb/472.b0b0/0/cntrl0stat", O_RDONLY);

     Control endpoints can be read and written. A read  operation
     receives  data  from  the device and a write operation sends
     data to the device.

     To perform a control-IN transfer, perform a write(2) of  USB
     setup data (see section 9.3 of the USB 1.1 or 2.0 specifica-
     tion) followed by a read(2) on the same control endpoint  to
     fetch the desired data. For example:

     void init_cntrl_req(
         uchar_t *req, uchar_t bmRequestType, uchar_t bRequest,
         ushort_t wValue, ushort_t wIndex, ushort_t wLength)
             {
                     req[0] = bmRequestType;
                     req[1] = bRequest;
                     req[2] = 0xFF & wValue;
                     req[3] = 0xFF & (wValue >> 8);
                     req[4] = 0xFF & wIndex;
                     req[5] = 0xFF & (wIndex >> 8);
                     req[6] = 0xFF & wLength;
                     req[7] = 0xFF & (wLength >> 8);
             }

             ....

             uchar_t dev_descr_req[8];
             usb_dev_descr_t descr;

             init_cntrl_req(dev_descr_req,
                 USB_DEV_REQ_DEV_TO_HOST, USB_REQ_GET_DESCR,
                 USB_DESCR_TYPE_SETUP_DEV, 0, sizeof (descr));

             count = write(fd, dev_descr_req, sizeof (dev_descr_req));
             if (count != sizeof (dev_descr_req)) {
                     /* do some error recovery */
                     ...
             }

             count = read(fd, &descr, sizeof (descr));
             if (count != sizeof (descr)) {
                     /* do some error recovery */
             }

     The application can issue any number of reads to  read  data
     received  on a control endpoint. ugen successfully completes
     all reads, returning the number of bytes  transferred.  Zero
     is returned when there is no data to transfer.

     If the read/write fails and returns -1, you can  access  the
     endpoint's  status  device  logical  name  for precise error
     information:

             int status;

             count = read(fdstat, &status, sizeof (status));
             if (count == sizeof (status)) {
                     switch (status) {
                     case USB_LC_STAT_SUSPENDED:
                     case USB_LC_STAT_DISCONNECTED:
                             /* close all endpoints */
                             ...
                             break;
                     default:
                             ...
                             break;
                     }
             }

     Refer to the ERRORS section for all possible error values.

     To  perform  a  control-OUT  transfer,  send  in  a   single
     transfer,  the  USB  setup data followed by any accompanying
     data bytes.

         /* 1st 8 bytes of wbuf are setup. */
         init_cntrl_req(wbuf, .......);

         /* Data bytes begin at byte 8 of wbuf. */
         bcopy(data, &wuf[8], sizeof (data);

         /* Send it all in a single transfer. */

          count = write(fd, wbuf, sizeof (wbuf));

     A write(2) returns the number of bytes (both setup and data)
     actually  transferred,  (whether  or  not  the write is com-
     pletely successful), provided that  some  data  is  actually
     transferred.  When  no data is transferred, write(2) returns
     -1. Applications can read the corresponding endpoint  status
     to  retrieve  detailed error information. Note that it is an
     error to specify a size different than:

          (number of data bytes + number of setup bytes).

     Here is a more extensive example which gets all  descriptors
     of  a device configuration. For sake of brevity, uninterest-
     ing parts are omitted.

        #include <sys/usb/usba.h>
        #include <sys/usb/clients/ugen/usb_ugen.h

        uchar_t *config_cloud;
        uchar_t *curr_descr;

        uchar_t *bytes;

        int curr_descr_len;
        int curr_descr_type;

        usb_cfg_descr_t cfg_descr;
        usb_if_descr_t if_descr;
        usb_ep_descr_t ep_descr;

        /* See 9.13 of USB 2.0 spec for ordering. */
        static char *pipetypes[] = {
             "Control", "Isochronous", "Bulk", "Interrupt"
        };

        /*
         * Setup to send a request to read just the config descriptor.  The
         * size of the whole cloud, containing all cfg, interface, endpoint,
         * class and vendor-specific descriptors, will be returned as part of
         * the config descriptor.
         */
        init_cntrl_req(&setup_data, USB_DEV_REQ_DEV_TO_HOST, USB_REQ_GET_DESCR,
                        USB_DESCR_TYPE_SETUP_CFG, 0, USB_CFG_DESCR_SIZE);

        /*
         * Write setup data. USB device will prepare to return the whole
         * config cloud as a response to this. We will read this separately.
         */
        count = write(ctrl_fd, &setup_data, sizeof (setup_data));
        if (count != sizeof (setup_data)) {
                 /* Error recovery. */
        } else {
                count = read(ctrl_fd, &cfg_descr, USB_CFG_DESCR_SIZE);
                if (count != USB_CFG_DESCR_SIZE) {
                         /* Error recovery. */
                }
        }

        /* USB data is little endian. */
        bytes = (uchar_t *)(&cfg_descr.wTotalLength);
        totalLength = bytes[0] + (bytes[1] << 8);

        /*
         * The size of the whole cloud is in the bLength field.  Set up
         * to read this amount of data, to get the whole cloud.
         */
        config_cloud = malloc(totalLength);

        init_cntrl_req(&setup_data, USB_DEV_REQ_DEV_TO_HOST, USB_REQ_GET_DESCR,
                        USB_DESCR_TYPE_SETUP_CFG, 0, totalLength);

        count = write(ctrl_fd, &setup_data, sizeof (setup_data));
        if (count != sizeof (setup_data)) {
                /* Error recovery. */
        } else {
                count = read(ctrl_fd, config_cloud, totalLength);
                if (count != totalLength) {
                        /* Error recovery. */
                 }
        }

        /* Got the data.  Now loop, dumping out the descriptors found. */

        curr_descr = config_cloud;
        offset = 0;
        while (offset < totalLength) {

                /* All descr have length and type at offset 0 and 1 */
                curr_descr_len = curr_descr[0];
                curr_descr_type = curr_descr[1];

                switch (curr_descr_type) {
                case USB_DESCR_TYPE_CFG:

                         /*
                          * Copy data into separate structure, needed for
                          * proper alignment of all non char fields.  Note:
                          * non-char fields of all descriptors begin on aligned
                          * boundaries.  The issue is that some structures may
                          * be adjacent to others which have an odd-numbered
                          * byte size, and may thus start on an odd-numbered
                          * boundary.  */
                         bcopy(curr_descr, &cfg_descr, curr_descr_len);

                         /* Remember to read any words in endian-neutral way. */

                         (void) printf("\nConfig %d found.\n",
                             cfg_descr.bConfigurationValue);
                         break;

                 case USB_DESCR_TYPE_IF:
                         bcopy(curr_descr, &if_descr, curr_descr_len);
                         (void) printf("\n\tInterface %d, Alt %d found.\n",
                             if_descr.bInterfaceNumber,
                             if_descr.bAlternateSetting);
                         break;

                 case USB_DESCR_TYPE_EP:
                         bcopy(curr_descr, &ep_descr, curr_descr_len);
                         (void) printf("\n\t\tEndpoint %d (%s-%s) found.\n",
                             (ep_descr.bEndpointAddress & USB_EP_NUM_MASK),
                             (pipetypes[
                                 ep_descr.bmAttributes & USB_EP_ATTR_MASK]),
                             ((ep_descr.bEndpointAddress &
                             USB_EP_DIR_IN) ? "IN" : "OUT"));
                          break;

                  default:
                          (void) printf(
                              "\n\t\t\tOther descriptor found.  Type:%d\n",
                              curr_descr_type);
                          break;

                  }

                  offset += curr_descr_len;
                  curr_descr = &config_cloud[offset];
        }


INTERRUPT-IN TRANSFERS

     Applications requiring data from  an  interrupt-IN  endpoint
     should  open  the  corresponding logical device name and use
     read(2), aioread(3AIO) and poll(2) system calls.

     An interrupt-IN endpoint must be opened  with  O_RDONLY.  It
     can also be opened using O_NONBLOCK or O_NDELAY if desired.

     fd = open("/dev/usb/472.b0b0/0/if0in1", O_RDONLY);

     fdstat = open("/dev/usb/472.b0b0/0/if0in1stat", O_RDONLY);

     ugen starts polling interrupt-IN endpoints immediately  upon
     opening  them  and stops polling them upon closure. (Polling
     refers to interrogation of the  device  by  the  driver  and
     should  not be confused with poll(2), which is an interroga-
     tion of the driver by the application.)

     A read(2) of an  endpoint  opened  with  the  O_NONBLOCK  or
     O_NDELAY flags set will not block when there is insufficient
     data available to  satisfy  the  request.  The  read  simply
     returns what it can without signifying any error.

     Applications  should  continuously  check  for  and  consume
     interrupt  data.  ugen enables buffering of up to one second
     of incoming data. In case of  buffer  overflow,  ugen  stops
     polling the interrupt-IN endpoint until the application con-
     sumes all the data. In this case,  a  read(2)  of  an  empty
     buffer   returns   -1,   sets   the   endpoint   status   to
     USB_LC_STAT_INTR_BUF_FULL (to indicate that the  buffer  had
     been  full  and polling had been stopped) and causes ugen to
     start polling the endpoint again. To  retrieve  the  status,
     the   application   can  open  and  read  the  corresponding
     endpoint's status device logical name.

     for (;;) {
             count = read(fd, buf, sizeof(buf));
             if (count == -1) {
                     int cnt, status;

                     cnt = read(fdstat, &status, sizeof (status));
                     if (cnt == -1) {
                              /* more error recovery here */
                     } else {
                             switch (status) {
                             case USB_LC_STAT_INTR_BUF_FULL:
                                    ...
                                    break;
                             default:
                                    ...
                                    break;
                             }
                     }
                }
                /* process the data */
                ....
             }

     ugen will never drop data. However, the device may drop data
     if  the  application  cannot  read it at the rate that it is
     produced.

     An application can open multiple interrupt-IN endpoints  and
     can  call  poll(2)  to monitor the availability of new data.
     (Note: poll works  with  interrupt-IN  data  endpoints,  not
     their status endpoints.)

             struct pollfd pfd[2];

             bzero(pfd, sizeof (pfd));
             pfd[0].fd = fd1;    /* fd1 is one interrupt-IN endpoint. */
             pfd[0].events = POLLIN;
             pfd[1].fd = fd2;    /* fd2 is another interrupt-IN endpoint. */
             pfd[1].events = POLLIN;

             for (;;) {
                     poll(pfd, 2, -1);

                     if (pfd[0].revents & POLLIN) {
                             count = read(fd1, buf, sizeof (buf));
                             ....
                     }
                     if (pfd[1].revents & POLLIN) {
                             count = read(fd2, buf, sizeof (buf));
                             ....
                     }
             }

     You can monitor the device status endpoint via poll(2)  con-
     currently  with the multiple interrupt-IN endpoints.  Simply
     add another pollfd element to the pfd array in the  previous
     code example, and initialize the new element's fd field with
     the file  descriptor  of the device status endpoint  (opened
     without  O_NONBLOCK   or   O_NDELAY).  Set the new element's
     event field to POLLIN like the  other  elements.  Note  that
     only  interrupt-IN  endpoints and the device status endpoint
     can be monitored using poll(2).


INTERRUPT-OUT TRANSFERS

     Applications requiring output on an  interrupt-OUT  endpoint
     can open the corresponding  logical  device name and perform
     regular  UNIX  I/O   system  calls  such  as  write(2)   and
     aiowrite(3AIO).

     An interrupt-OUT endpoint must be opened with O_WRONLY.

     fd = open("/dev/usb/472.b0b0/0/if0out3", O_WRONLY);

     fdstat = open("/dev/usb/472.b0b0/0/if0out3stat", O_RDONLY);

     Data can be written to an interrupt-OUT endpoint as follows:

           count = write(fd, buf, sizeof (buf)):
           if (count == -1) {
                  /* error recovery */
           }


BULK TRANSFERS

     Applications requiring I/O on a bulk endpoint can  open  the
     corresponding  logical  device name and perform regular UNIX
     I/O  system   calls.   For   example:   read(2),   write(2),
     aioread(3AIO)  and  aiowrite(3AIO). poll(2) is not supported
     on bulk endpoints.

     A bulk endpoint must be opened with O_RDONLY or O_WRONLY and
     cannot be opened with O_NONBLOCK or O_NDELAY:

     fd = open("/dev/usb/472.b0b0/0/if0in2", O_RDONLY);

     fdstat = open("/dev/usb/472.b0b0/0/if0in2stat", O_RDONLY);

     Data can be read from a bulk-IN endpoint as follows:

             count = read(fd, buf, sizeof (buf)):
             if (count == -1) {
                     /* error recovery */
             }

      Data can be written to a bulk-OUT endpoint as follows:

             count = write(fd, buf, sizeof (buf)):
             if (count == -1) {
                     /* error recovery */
             }


ERRORS

     The following statuses are returned by endpoint status  dev-
     ice logical names:

     USB_LC_STAT_NOERROR
           No error.

     USB_LC_STAT_CRC
           CRC error detected.

     USB_LC_STAT_BITSTUFFING
           Bit stuffing error.

     USB_LC_STAT_DATA_TOGGLE_MM
           Data toggle did not match.

     USB_LC_STAT_STALL
           Endpoint returned stall.

     USB_LC_STAT_DEV_NOT_RESP
           Device not responding.

     USB_LC_STAT_UNEXP_PID
           Unexpected Packet Identifier (PID).

     USB_LC_STAT_PID_CHECKFAILURE
           Check bits on PID failed.

     USB_LC_STAT_DATA_OVERRUN
           Data overrun.

     USB_LC_STAT_DATA_UNDERRUN
           Data underrun.

     USB_LC_STAT_BUFFER_OVERRUN
           Buffer overrun.

     USB_LC_STAT_BUFFER_UNDERRUN
           Buffer underrun.

     USB_LC_STAT_TIMEOUT
           Command timed out.

     USB_LC_STAT_NOT_ACCESSED
           Not accessed by the hardware.

     USB_LC_STAT_UNSPECIFIED_ERR
           Unspecified USBA or HCD error.

     USB_LC_STAT_NO_BANDWIDTH
           No bandwidth available.

     USB_LC_STAT_HW_ERR
           Host Controller h/w error.

     USB_LC_STAT_SUSPENDED
           Device was suspended.

     USB_LC_STAT_DISCONNECTED
           Device was disconnected.

     USB_LC_STAT_INTR_BUF_FULL
           Polling was stopped as the  interrupt-IN  data  buffer
           was  full.   Buffer is now empty  and polling has been
           resumed.

     USB_LC_STAT_INTERRUPTED
           Request was interrupted.

     USB_LC_STAT_NO_RESOURCES
           No resources available for request.

     USB_LC_STAT_INTR_POLLING_FAILED
           Failed to restart polling.

     The following system call errno values are returned:

     EBUSY The endpoint has  been  opened  and  another  open  is
           attempted.

     EACCES
           An endpoint open has  been  attempted  with  incorrect
           flags.

     ENOTSUP
           Operation not supported.

     ENXIO Device associated with the file  descriptor  does  not
           exist.

     ENODEV
           Device has been hot-removed or a  suspend/resume  hap-
           pened before this command.

     EIO   An I/O error occurred. Send a  read  on  the  endpoint
           status minor node to get the exact error information.

     EINTR Interrupted system call.

     ENOMEM
           No memory for the allocation of internal structures.


FILES


             /dev/usb/<vid>.<pid>/<N>/cntrl0
             /dev/usb/<vid>.<pid>/<N>/cntrl0stat

             /dev/usb/<vid>.<pid>/<N>/if<interface#>
                             <in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/if<interface#>
                             <in|out|cntrl><endpoint#>stat

             /dev/usb/<vid>.<pid>/<N>/if<interface#>.
                             <alternate><in|out|cntrl<endpoint#>
             /dev/usb/<vid>.<pid>/<N>/if<interface#>.
                             <alternate><in|out|cntrl><endpoint#>stat

             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>
                             <in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>
                             <in|out|cntrl<endpoint#stat>

             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>.
                             <alternate><in|out|cntrl><endpoint#>
             /dev/usb/<vid>.<pid>/<N>/cfg<value>if<interface#>.
                             <alternate><in|out|cntrl><endpoint#>stat

             /dev/usb/<vid>.<pid>/<N>/devstat

             /dev/usb/<vid>.<pid>/<N>/if<interface#>cntrl0
             /dev/usb/<vid>.<pid>/<N>/if<interface#>cntrl0stat

     where N is an integer representing the  instance  number  of
     this  type of device. (All logical device names for a single
     device share the same N.)

     /kernel/drv/usba10_ugen
           32 bit ELF kernel module for USBA 1.0 framework.*

     /kernel/drv/sparcv9/usba10_ugen
           64 bit ELF kernel  module  for  USBA  1.0  framework.*
           (SPARC only).

     /kernel/drv/usba10_ugen.conf
           Configuration file needed for usba10_ugen.

     * Please see www.sun.com/desktop/whitepapers.html  for  more
     information  regarding  USB  dual  framework implementation,
     USBA 1.0, and USB 2.0.


ATTRIBUTES

     See attributes(5) for descriptions of the  following  attri-
     butes:

     ____________________________________________________________
   |        ATTRIBUTE TYPE       |        ATTRIBUTE VALUE      |
   | ____________________________|_____________________________|_
   |  Architecture               |  PCI-based systems          |
   | ____________________________|_____________________________|_
   |  Availability               |  SUNWusb (All architectures)|
   |                             |  SUNWusbx (SPARC only)      |
   |_____________________________|_____________________________|


SEE ALSO

      update_drv(1M), usba(7D)

     http://www.sun.com/desktop/whitepapers.html


DIAGNOSTICS

     In addition to being  logged,  the  following  messages  may
     appear  on the system console. All messages are formatted in
     the following manner:

     Warning: <device path> (usba10_ugen<instance num>): Error Message...

     Too many minor nodes
           Device has too many minor nodes. Not  all  are  avail-
           able.

     Instance number too high (<number>).
           Too many devices are using this driver.

     Cannot access <device>. Please reconnect.
           This device has been  disconnected  because  a  device
           other  than  the  original  one has been inserted. The
           driver informs you of this fact by displaying the name
           of the original device.


disconnect and reconnect.

     Device is not identical to the previous one on this port.  Please
           Same   condition  as  described above; however in this
           case, the driver is unable to  identify  the  original
           device with a name string.


NOTES

     Isochronous transfers are not supported.

     ugen returns -1 for all commands and sets  errno  to  ENODEV
     when  device has been hot-removed or resumed from a suspend.
     The application must close and reopen all open  minor  nodes
     to reinstate successful communication.

     ugen is available only through USB 2.0 ports operated by the
     USBA         1.0         framework.        Please        see
     www.sun.com/desktop/whitepapers.html  for  more  information
     regarding  USB  dual framework implementation, USBA 1.0, and
     USB 2.0.


Man(1) output converted with man2html