Author: thompsa
Date: Sat Jun 27 21:23:30 2009
New Revision: 195121
URL: http://svn.freebsd.org/changeset/base/195121

Log:
  Sync to p4
  
   - Add support for devices that handle set and clear stall in hardware.
   - Add missing get timestamp function
   - Add more xfer flags
  
  Submitted by: Hans Petter Selasky
  Approved by:  re (kib)

Modified:
  head/sys/dev/usb/controller/at91dci.c
  head/sys/dev/usb/controller/atmegadci.c
  head/sys/dev/usb/controller/avr32dci.c
  head/sys/dev/usb/controller/musb_otg.c
  head/sys/dev/usb/controller/uss820dci.c
  head/sys/dev/usb/net/if_cdce.c
  head/sys/dev/usb/storage/ustorage_fs.c
  head/sys/dev/usb/usb_controller.h
  head/sys/dev/usb/usb_device.c
  head/sys/dev/usb/usb_handle_request.c
  head/sys/dev/usb/usb_if.m
  head/sys/dev/usb/usb_transfer.c
  head/sys/dev/usb/usbdi.h

Modified: head/sys/dev/usb/controller/at91dci.c
==============================================================================
--- head/sys/dev/usb/controller/at91dci.c       Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/controller/at91dci.c       Sat Jun 27 21:23:30 2009        
(r195121)
@@ -1227,7 +1227,7 @@ at91dci_device_done(struct usb_xfer *xfe
 
 static void
 at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
        struct at91dci_softc *sc;
        uint32_t csr_val;

Modified: head/sys/dev/usb/controller/atmegadci.c
==============================================================================
--- head/sys/dev/usb/controller/atmegadci.c     Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/controller/atmegadci.c     Sat Jun 27 21:23:30 2009        
(r195121)
@@ -1113,7 +1113,7 @@ atmegadci_device_done(struct usb_xfer *x
 
 static void
 atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
        struct atmegadci_softc *sc;
        uint8_t ep_no;

Modified: head/sys/dev/usb/controller/avr32dci.c
==============================================================================
--- head/sys/dev/usb/controller/avr32dci.c      Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/controller/avr32dci.c      Sat Jun 27 21:23:30 2009        
(r195121)
@@ -1081,7 +1081,7 @@ avr32dci_device_done(struct usb_xfer *xf
 
 static void
 avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
        struct avr32dci_softc *sc;
        uint8_t ep_no;

Modified: head/sys/dev/usb/controller/musb_otg.c
==============================================================================
--- head/sys/dev/usb/controller/musb_otg.c      Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/controller/musb_otg.c      Sat Jun 27 21:23:30 2009        
(r195121)
@@ -1473,7 +1473,7 @@ musbotg_device_done(struct usb_xfer *xfe
 
 static void
 musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
        struct musbotg_softc *sc;
        uint8_t ep_no;

Modified: head/sys/dev/usb/controller/uss820dci.c
==============================================================================
--- head/sys/dev/usb/controller/uss820dci.c     Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/controller/uss820dci.c     Sat Jun 27 21:23:30 2009        
(r195121)
@@ -1202,7 +1202,7 @@ uss820dci_device_done(struct usb_xfer *x
 
 static void
 uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
        struct uss820dci_softc *sc;
        uint8_t ep_no;

Modified: head/sys/dev/usb/net/if_cdce.c
==============================================================================
--- head/sys/dev/usb/net/if_cdce.c      Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/net/if_cdce.c      Sat Jun 27 21:23:30 2009        
(r195121)
@@ -764,7 +764,7 @@ tr_setup:
 static int
 cdce_handle_request(device_t dev,
     const void *req, void **pptr, uint16_t *plen,
-    uint16_t offset, uint8_t is_complete)
+    uint16_t offset, uint8_t *pstate)
 {
        return (ENXIO);                 /* use builtin handler */
 }

Modified: head/sys/dev/usb/storage/ustorage_fs.c
==============================================================================
--- head/sys/dev/usb/storage/ustorage_fs.c      Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/storage/ustorage_fs.c      Sat Jun 27 21:23:30 2009        
(r195121)
@@ -475,10 +475,11 @@ ustorage_fs_transfer_stop(struct ustorag
 static int
 ustorage_fs_handle_request(device_t dev,
     const void *preq, void **pptr, uint16_t *plen,
-    uint16_t offset, uint8_t is_complete)
+    uint16_t offset, uint8_t *pstate)
 {
        struct ustorage_fs_softc *sc = device_get_softc(dev);
        const struct usb_device_request *req = preq;
+       uint8_t is_complete = *pstate;
 
        if (!is_complete) {
                if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&

Modified: head/sys/dev/usb/usb_controller.h
==============================================================================
--- head/sys/dev/usb/usb_controller.h   Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/usb_controller.h   Sat Jun 27 21:23:30 2009        
(r195121)
@@ -96,7 +96,7 @@ struct usb_bus_methods {
        /* USB Device mode only - Mandatory */
 
        void    (*get_hw_ep_profile) (struct usb_device *udev, const struct 
usb_hw_ep_profile **ppf, uint8_t ep_addr);
-       void    (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, 
struct usb_endpoint *ep);
+       void    (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, 
struct usb_endpoint *ep, uint8_t *did_stall);
        void    (*clear_stall) (struct usb_device *udev, struct usb_endpoint 
*ep);
 
 };

Modified: head/sys/dev/usb/usb_device.c
==============================================================================
--- head/sys/dev/usb/usb_device.c       Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/usb_device.c       Sat Jun 27 21:23:30 2009        
(r195121)
@@ -936,7 +936,7 @@ usbd_set_endpoint_stall(struct usb_devic
                 * complete the USB transfer like in case of a timeout
                 * setting the error code "USB_ERR_STALLED".
                 */
-               (udev->bus->methods->set_stall) (udev, xfer, ep);
+               (udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall);
        }
        if (!do_stall) {
                ep->toggle_next = 0;    /* reset data toggle */

Modified: head/sys/dev/usb/usb_handle_request.c
==============================================================================
--- head/sys/dev/usb/usb_handle_request.c       Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/usb_handle_request.c       Sat Jun 27 21:23:30 2009        
(r195121)
@@ -198,6 +198,7 @@ usb_handle_iface_request(struct usb_xfer
        struct usb_device *udev = xfer->xroot->udev;
        int error;
        uint8_t iface_index;
+       uint8_t temp_state;
 
        if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
                iface_index = req.wIndex[0];    /* unicast */
@@ -222,6 +223,10 @@ tr_repeat:
                /* end of interfaces non-existing interface */
                goto tr_stalled;
        }
+       /* set initial state */
+
+       temp_state = state;
+
        /* forward request to interface, if any */
 
        if ((error != 0) &&
@@ -233,7 +238,7 @@ tr_repeat:
 #endif
                error = USB_HANDLE_REQUEST(iface->subdev,
                    &req, ppdata, plen,
-                   off, state);
+                   off, &temp_state);
        }
        iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
 
@@ -252,14 +257,18 @@ tr_repeat:
            (iface_parent->subdev != iface->subdev) &&
            device_is_attached(iface_parent->subdev)) {
                error = USB_HANDLE_REQUEST(iface_parent->subdev,
-                   &req, ppdata, plen, off,
-                   state);
+                   &req, ppdata, plen, off, &temp_state);
        }
        if (error == 0) {
                /* negativly adjust pointer and length */
                *ppdata = ((uint8_t *)(*ppdata)) - off;
                *plen += off;
-               goto tr_valid;
+
+               if ((state == USB_HR_NOT_COMPLETE) &&
+                   (temp_state == USB_HR_COMPLETE_OK))
+                       goto tr_short;
+               else
+                       goto tr_valid;
        } else if (error == ENOTTY) {
                goto tr_stalled;
        }
@@ -337,6 +346,12 @@ tr_valid:
        USB_XFER_LOCK(xfer);
        return (0);
 
+tr_short:
+       mtx_unlock(&Giant);
+       sx_unlock(udev->default_sx + 1);
+       USB_XFER_LOCK(xfer);
+       return (USB_ERR_SHORT_XFER);
+
 tr_stalled:
        mtx_unlock(&Giant);
        sx_unlock(udev->default_sx + 1);
@@ -444,6 +459,7 @@ usb_handle_request(struct usb_xfer *xfer
        uint16_t wValue;
        uint16_t wIndex;
        uint8_t state;
+       uint8_t is_complete = 1;
        usb_error_t err;
        union {
                uWord   wStatus;
@@ -596,6 +612,9 @@ usb_handle_request(struct usb_xfer *xfer
                    USB_ADD_BYTES(&src_zcopy, 0),
                    &max_len, req, off, state);
                if (err == 0) {
+                       is_complete = 0;
+                       goto tr_valid;
+               } else if (err == USB_ERR_SHORT_XFER) {
                        goto tr_valid;
                }
                /*
@@ -735,7 +754,7 @@ tr_valid:
        if (rem > xfer->max_data_length) {
                rem = usbd_xfer_max_len(xfer);
        }
-       if (rem != max_len) {
+       if ((rem != max_len) && (is_complete != 0)) {
                /*
                 * If we don't transfer the data we can transfer, then
                 * the transfer is short !

Modified: head/sys/dev/usb/usb_if.m
==============================================================================
--- head/sys/dev/usb/usb_if.m   Sat Jun 27 21:21:11 2009        (r195120)
+++ head/sys/dev/usb/usb_if.m   Sat Jun 27 21:23:30 2009        (r195121)
@@ -36,6 +36,11 @@ INTERFACE usb;
 
 # The device received a control request
 #
+# The value pointed to by "pstate" can be updated to
+# "USB_HR_COMPLETE_OK" to indicate that the control
+# read transfer is complete, in case of short USB
+# control transfers.
+#
 # Return values:
 # 0: Success
 # ENOTTY: Transaction stalled
@@ -47,5 +52,5 @@ METHOD int handle_request {
        void **pptr; /* data pointer */
        uint16_t *plen; /* maximum transfer length */
        uint16_t offset; /* data offset */
-       uint8_t is_complete; /* set if transfer is complete, see USB_HR_XXX */
+       uint8_t *pstate; /* set if transfer is complete, see USB_HR_XXX */
 };

Modified: head/sys/dev/usb/usb_transfer.c
==============================================================================
--- head/sys/dev/usb/usb_transfer.c     Sat Jun 27 21:21:11 2009        
(r195120)
+++ head/sys/dev/usb/usb_transfer.c     Sat Jun 27 21:23:30 2009        
(r195121)
@@ -2352,29 +2352,37 @@ usbd_pipe_start(struct usb_xfer_queue *p
                    (type == UE_INTERRUPT)) {
                        struct usb_device *udev;
                        struct usb_xfer_root *info;
+                       uint8_t did_stall;
 
                        info = xfer->xroot;
                        udev = info->udev;
-                       ep->is_stalled = 1;
+                       did_stall = 1;
 
                        if (udev->flags.usb_mode == USB_MODE_DEVICE) {
                                (udev->bus->methods->set_stall) (
-                                   udev, NULL, ep);
+                                   udev, NULL, ep, &did_stall);
                        } else if (udev->default_xfer[1]) {
                                info = udev->default_xfer[1]->xroot;
-                               if (usb_proc_msignal(
+                               usb_proc_msignal(
                                    &info->bus->non_giant_callback_proc,
-                                   &udev->cs_msg[0], &udev->cs_msg[1])) {
-                                       /* ignore */
-                               }
+                                   &udev->cs_msg[0], &udev->cs_msg[1]);
                        } else {
                                /* should not happen */
                                DPRINTFN(0, "No stall handler!\n");
                        }
                        /*
-                        * We get started again when the stall is cleared!
+                        * Check if we should stall. Some USB hardware
+                        * handles set- and clear-stall in hardware.
                         */
-                       return;
+                       if (did_stall) {
+                               /*
+                                * The transfer will be continued when
+                                * the clear-stall control endpoint
+                                * message is received.
+                                */
+                               ep->is_stalled = 1;
+                               return;
+                       }
                }
        }
        /* Set or clear stall complete - special case */
@@ -2966,6 +2974,12 @@ usbd_xfer_set_flag(struct usb_xfer *xfer
                case USB_SHORT_XFER_OK:
                        xfer->flags.short_xfer_ok = 1;
                        break;
+               case USB_MULTI_SHORT_OK:
+                       xfer->flags.short_frames_ok = 1;
+                       break;
+               case USB_MANUAL_STATUS:
+                       xfer->flags.manual_status = 1;
+                       break;
        }
 }
 
@@ -2979,5 +2993,22 @@ usbd_xfer_clr_flag(struct usb_xfer *xfer
                case USB_SHORT_XFER_OK:
                        xfer->flags.short_xfer_ok = 0;
                        break;
+               case USB_MULTI_SHORT_OK:
+                       xfer->flags.short_frames_ok = 0;
+                       break;
+               case USB_MANUAL_STATUS:
+                       xfer->flags.manual_status = 0;
+                       break;
        }
 }
+
+/*
+ * The following function returns in milliseconds when the isochronous
+ * transfer was completed by the hardware. The returned value wraps
+ * around 65536 milliseconds.
+ */
+uint16_t
+usbd_xfer_get_timestamp(struct usb_xfer *xfer)
+{
+       return (xfer->isoc_time_complete);
+}

Modified: head/sys/dev/usb/usbdi.h
==============================================================================
--- head/sys/dev/usb/usbdi.h    Sat Jun 27 21:21:11 2009        (r195120)
+++ head/sys/dev/usb/usbdi.h    Sat Jun 27 21:23:30 2009        (r195121)
@@ -78,6 +78,8 @@ typedef enum {        /* keep in sync with usb_
 #define        USB_SHORT_XFER_OK       0x0004  /* allow short reads */
 #define        USB_DELAY_STATUS_STAGE  0x0010  /* insert delay before STATUS 
stage */
 #define        USB_USER_DATA_PTR       0x0020  /* internal flag */
+#define        USB_MULTI_SHORT_OK      0x0040  /* allow multiple short frames 
*/
+#define        USB_MANUAL_STATUS       0x0080  /* manual ctrl status */
 
 #define        USB_NO_TIMEOUT 0
 #define        USB_DEFAULT_TIMEOUT 5000        /* 5000 ms = 5 seconds */
@@ -486,6 +488,7 @@ void        usbd_xfer_set_stall(struct usb_xfer
 int    usbd_xfer_is_stalled(struct usb_xfer *xfer);
 void   usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
 void   usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
+uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
 
 void   usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
            const void *ptr, usb_frlength_t len);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to