hub alternate interface wip

Change-Id: Ib35bcbe76e7bbf444ba9260d3def60e38317c68d
diff --git a/system/dev/usb/dwc2/dwc2.c b/system/dev/usb/dwc2/dwc2.c
index 3c095bf..db8c4b9 100644
--- a/system/dev/usb/dwc2/dwc2.c
+++ b/system/dev/usb/dwc2/dwc2.c
@@ -603,7 +603,7 @@
     return ZX_OK;
 }
 
-zx_status_t dwc_config_hub(void* ctx, uint32_t device_id, usb_speed_t speed,
+zx_status_t dwc_config_hub(void* ctx, uint32_t device_id, usb_speed_t speed, bool multi_tt,
                            usb_hub_descriptor_t* descriptor) {
     // Not sure if DWC controller has to take any specific action here.
     return ZX_OK;
diff --git a/system/dev/usb/usb-bus/usb-bus.c b/system/dev/usb/usb-bus/usb-bus.c
index 6ecc772..87b5277 100644
--- a/system/dev/usb/usb-bus/usb-bus.c
+++ b/system/dev/usb/usb-bus/usb-bus.c
@@ -59,13 +59,13 @@
 };
 
 static zx_status_t bus_configure_hub(void* ctx, zx_device_t* hub_device, usb_speed_t speed,
-                                         usb_hub_descriptor_t* descriptor) {
+                                     bool multi_tt, usb_hub_descriptor_t* descriptor) {
     usb_bus_t* bus = ctx;
     uint32_t hub_id;
     if (usb_interface_get_device_id(hub_device, &hub_id) != ZX_OK) {
         return ZX_ERR_INTERNAL;
     }
-    return usb_hci_configure_hub(&bus->hci, hub_id, speed, descriptor);
+    return usb_hci_configure_hub(&bus->hci, hub_id, speed, multi_tt, descriptor);
 }
 
 static zx_status_t bus_device_added(void* ctx, zx_device_t* hub_device, int port, usb_speed_t speed) {
diff --git a/system/dev/usb/usb-bus/usb-device.c b/system/dev/usb/usb-bus/usb-device.c
index 7235ff6..1b6b750 100644
--- a/system/dev/usb/usb-bus/usb-device.c
+++ b/system/dev/usb/usb-bus/usb-device.c
@@ -39,11 +39,13 @@
 
 zx_status_t usb_device_set_interface(usb_device_t* device, uint8_t interface_id,
                                      uint8_t alt_setting) {
+printf("usb_device_set_interface 1\n");
     mtx_lock(&device->interface_mutex);
     usb_interface_t* intf;
     list_for_every_entry(&device->children, intf, usb_interface_t, node) {
         if (usb_interface_contains_interface(intf, interface_id)) {
             mtx_unlock(&device->interface_mutex);
+printf("usb_device_set_interface 4\n");
             return usb_interface_set_alt_setting(intf, interface_id, alt_setting);
         }
     }
diff --git a/system/dev/usb/usb-bus/usb-interface.c b/system/dev/usb/usb-bus/usb-interface.c
index e9860cd..d5e33ff 100644
--- a/system/dev/usb/usb-bus/usb-interface.c
+++ b/system/dev/usb/usb-bus/usb-interface.c
@@ -164,6 +164,8 @@
     bool interface_endpoints[USB_MAX_EPS] = {};
     zx_status_t status = ZX_OK;
 
+printf("usb_interface_configure_endpoints 1\n");
+
     // iterate through our descriptors to find which endpoints should be active
     usb_descriptor_header_t* header = intf->descriptor;
     usb_descriptor_header_t* end = (usb_descriptor_header_t*)((void*)header + intf->descriptor_length);
@@ -171,6 +173,7 @@
 
     bool enable_endpoints = false;
     while (header < end) {
+printf("top of loop\n");
         if (header->bDescriptorType == USB_DT_INTERFACE) {
             usb_interface_descriptor_t* intf_desc = (usb_interface_descriptor_t*)header;
             cur_interface = intf_desc->bInterfaceNumber;
@@ -186,14 +189,18 @@
         header = NEXT_DESCRIPTOR(header);
     }
 
+printf("usb_interface_configure_endpoints 2\n");
+
     // update to new set of endpoints
     // FIXME - how do we recover if we fail half way through processing the endpoints?
     for (size_t i = 0; i < countof(new_endpoints); i++) {
+printf("for loop %zu\n", i);
         if (interface_endpoints[i]) {
             usb_endpoint_descriptor_t* old_ep = intf->active_endpoints[i];
             usb_endpoint_descriptor_t* new_ep = new_endpoints[i];
             if (old_ep != new_ep) {
                 if (old_ep) {
+printf("enable false\n");
                     zx_status_t ret = usb_interface_enable_endpoint(intf, old_ep, NULL, false);
                     if (ret != ZX_OK) status = ret;
                 }
@@ -205,6 +212,7 @@
                         && next->bDescriptorType == USB_DT_SS_EP_COMPANION) {
                         ss_comp_desc = (usb_ss_ep_comp_descriptor_t *)next;
                     }
+printf("enable true\n");
                     zx_status_t ret = usb_interface_enable_endpoint(intf, new_ep, ss_comp_desc, true);
                     if (ret != ZX_OK) status = ret;
                 }
@@ -212,6 +220,7 @@
             }
         }
     }
+printf("usb_interface_configure_endpoints 99\n");
     return status;
 }
 
@@ -321,6 +330,13 @@
     return intf->device_id;
 }
 
+static zx_status_t usb_interface_get_device_descriptor(void* ctx,
+                                                       usb_device_descriptor_t* out_desc) {
+    usb_interface_t* intf = ctx;
+    memcpy(out_desc, &intf->device->device_desc, sizeof(intf->device->device_desc));
+    return ZX_OK;
+}
+
 static zx_status_t usb_interface_get_descriptor_list(void* ctx, void** out_descriptors,
                                                      size_t* out_length) {
     usb_interface_t* intf = ctx;
@@ -634,9 +650,11 @@
 
 zx_status_t usb_interface_set_alt_setting(usb_interface_t* intf, uint8_t interface_id,
                                           uint8_t alt_setting) {
+printf("usb_interface_set_alt_setting 1\n");
     zx_status_t status = usb_interface_configure_endpoints(intf, interface_id, alt_setting);
     if (status != ZX_OK) return status;
 
+printf("usb_interface_set_alt_setting 2\n");
     return usb_device_control(intf->device,
                               USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE,
                               USB_REQ_SET_INTERFACE, alt_setting, interface_id, NULL, 0);
diff --git a/system/dev/usb/usb-hub/usb-hub.c b/system/dev/usb/usb-hub/usb-hub.c
index fcaff7b..33bae73 100644
--- a/system/dev/usb/usb-hub/usb-hub.c
+++ b/system/dev/usb/usb-hub/usb-hub.c
@@ -304,7 +304,31 @@
         goto fail;
     }
 
-    result = usb_bus_configure_hub(&hub->bus, hub->usb_device, hub->hub_speed, &desc);
+    bool multi_tt = false;
+    if (hub->hub_speed == USB_SPEED_HIGH) {
+printf("USB_SPEED_HIGH\n");
+        usb_device_descriptor_t device_desc;
+        size_t out_length;
+        zx_status_t status = usb_get_descriptor(&hub->usb, USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+                                            USB_DT_DEVICE, 0, &device_desc, sizeof(device_desc),
+                                            ZX_TIME_INFINITE, &out_length);
+printf("status %d out_length %zu bDeviceProtocol %u\n", status, out_length, device_desc.bDeviceProtocol);
+
+
+
+        if (status == ZX_OK && out_length == sizeof(device_desc) &&
+            device_desc.bDeviceProtocol == USB_HUB_MULTI_TT) {
+printf("call usb_set_interface\n");
+            status = usb_set_interface(&hub->usb, 0, 1);
+printf("set interface got %d\n", status);
+            if (status == ZX_OK) {
+printf("multi_TT\n");
+                multi_tt = true;
+            }
+        }
+    }
+
+    result = usb_bus_configure_hub(&hub->bus, hub->usb_device, hub->hub_speed, multi_tt, &desc);
     if (result < 0) {
         zxlogf(ERROR, "configure_hub failed: %d\n", result);
         goto fail;
diff --git a/system/dev/usb/usb-virtual-bus/usb-virtual-host.c b/system/dev/usb/usb-virtual-bus/usb-virtual-host.c
index d484a20..3b32287 100644
--- a/system/dev/usb/usb-virtual-bus/usb-virtual-host.c
+++ b/system/dev/usb/usb-virtual-bus/usb-virtual-host.c
@@ -70,7 +70,7 @@
     return 0;
 }
 
-zx_status_t virt_host_config_hub(void* ctx, uint32_t device_id, usb_speed_t speed,
+zx_status_t virt_host_config_hub(void* ctx, uint32_t device_id, usb_speed_t speed, bool multi_tt,
                                  usb_hub_descriptor_t* descriptor) {
     return ZX_OK;
 }
diff --git a/system/dev/usb/xhci/usb-xhci.c b/system/dev/usb/xhci/usb-xhci.c
index 8181ca4..485c7d6 100644
--- a/system/dev/usb/xhci/usb-xhci.c
+++ b/system/dev/usb/xhci/usb-xhci.c
@@ -87,10 +87,10 @@
     return xhci_get_current_frame(xhci);
 }
 
-static zx_status_t xhci_config_hub(void* ctx, uint32_t device_id, usb_speed_t speed,
+static zx_status_t xhci_config_hub(void* ctx, uint32_t device_id, usb_speed_t speed, bool multi_tt,
                             usb_hub_descriptor_t* descriptor) {
     xhci_t* xhci = ctx;
-    return xhci_configure_hub(xhci, device_id, speed, descriptor);
+    return xhci_configure_hub(xhci, device_id, speed, multi_tt, descriptor);
 }
 
 static zx_status_t xhci_hub_device_added(void* ctx, uint32_t hub_address, int port,
diff --git a/system/dev/usb/xhci/xhci-device-manager.c b/system/dev/usb/xhci/xhci-device-manager.c
index 924e2af..7957f13 100644
--- a/system/dev/usb/xhci/xhci-device-manager.c
+++ b/system/dev/usb/xhci/xhci-device-manager.c
@@ -131,12 +131,12 @@
             io_buffer_cache_op(&slot->buffer, ZX_VMO_OP_CACHE_INVALIDATE, 0,
                                sizeof(xhci_slot_context_t));
 #endif
-            mtt = XHCI_GET_BITS32(&slot->sc->sc0, SLOT_CTX_MTT_START, SLOT_CTX_MTT_BITS);
+            mtt = XHCI_READ32(&slot->sc->sc0) & SLOT_CTX_MTT;
             tt_hub_slot_id = hub_address;
             tt_port_number = port;
         }
     }
-    XHCI_SET_BITS32(&sc->sc0, SLOT_CTX_MTT_START, SLOT_CTX_MTT_BITS, mtt);
+    XHCI_SET32(&sc->sc0, SLOT_CTX_MTT, mtt);
     XHCI_SET_BITS32(&sc->sc2, SLOT_CTX_TT_HUB_SLOT_ID_START, SLOT_CTX_TT_HUB_SLOT_ID_BITS,
                     tt_hub_slot_id);
     XHCI_SET_BITS32(&sc->sc2, SLOT_CTX_TT_PORT_NUM_START, SLOT_CTX_TT_PORT_NUM_BITS,
@@ -677,7 +677,7 @@
     return status;
 }
 
-zx_status_t xhci_configure_hub(xhci_t* xhci, uint32_t slot_id, usb_speed_t speed,
+zx_status_t xhci_configure_hub(xhci_t* xhci, uint32_t slot_id, usb_speed_t speed, bool multi_tt,
                                usb_hub_descriptor_t* descriptor) {
     zxlogf(TRACE, "xhci_configure_hub slot_id: %d speed: %d\n", slot_id, speed);
     if (xhci_is_root_hub(xhci, slot_id)) {
@@ -704,7 +704,12 @@
 #if XHCI_USE_CACHE_OPS
      io_buffer_cache_op(&slot->buffer, ZX_VMO_OP_CACHE_INVALIDATE, 0, sizeof(xhci_slot_context_t));
 #endif
-    XHCI_WRITE32(&sc->sc0, XHCI_READ32(&slot->sc->sc0) | SLOT_CTX_HUB);
+    uint32_t sc0 = XHCI_READ32(&slot->sc->sc1);
+    sc0 |= SLOT_CTX_HUB;
+    if (multi_tt) {
+        sc0 |= SLOT_CTX_MTT;
+    }
+    XHCI_WRITE32(&sc->sc0, sc0);
     XHCI_WRITE32(&sc->sc1, XHCI_READ32(&slot->sc->sc1));
     XHCI_WRITE32(&sc->sc2, XHCI_READ32(&slot->sc->sc2));
 
diff --git a/system/dev/usb/xhci/xhci-device-manager.h b/system/dev/usb/xhci/xhci-device-manager.h
index e7a191b..7102a9b 100644
--- a/system/dev/usb/xhci/xhci-device-manager.h
+++ b/system/dev/usb/xhci/xhci-device-manager.h
@@ -18,5 +18,5 @@
 zx_status_t xhci_queue_start_root_hubs(xhci_t* xhci);
 zx_status_t xhci_enable_endpoint(xhci_t* xhci, uint32_t slot_id, usb_endpoint_descriptor_t* ep_desc,
                                  usb_ss_ep_comp_descriptor_t* ss_comp_desc, bool enable);
-zx_status_t xhci_configure_hub(xhci_t* xhci, uint32_t slot_id, usb_speed_t speed,
+zx_status_t xhci_configure_hub(xhci_t* xhci, uint32_t slot_id, usb_speed_t speed, bool multi_tt,
                                usb_hub_descriptor_t* descriptor);
diff --git a/system/dev/usb/xhci/xhci-hw.h b/system/dev/usb/xhci/xhci-hw.h
index 59f9ae6..dccf9ef 100644
--- a/system/dev/usb/xhci/xhci-hw.h
+++ b/system/dev/usb/xhci/xhci-hw.h
@@ -470,8 +470,7 @@
 #define SLOT_CTX_ROUTE_STRING_BITS          20
 #define SLOT_CTX_SPEED_START                20
 #define SLOT_CTX_SPEED_BITS                 4
-#define SLOT_CTX_MTT_START                  25
-#define SLOT_CTX_MTT_BITS                   1
+#define SLOT_CTX_MTT                        (1 << 25)
 #define SLOT_CTX_HUB                        (1 << 26)
 #define SLOT_CTX_CONTEXT_ENTRIES_START      27
 #define SLOT_CTX_CONTEXT_ENTRIES_BITS       5
diff --git a/system/public/zircon/hw/usb-hub.h b/system/public/zircon/hw/usb-hub.h
index 2a8b395..c524d48 100644
--- a/system/public/zircon/hw/usb-hub.h
+++ b/system/public/zircon/hw/usb-hub.h
@@ -12,6 +12,12 @@
 #define USB_RECIP_HUB   (USB_TYPE_CLASS | USB_RECIP_DEVICE)
 #define USB_RECIP_PORT  (USB_TYPE_CLASS | USB_RECIP_OTHER)
 
+// Hub device protocols
+#define USB_HUB_NO_TT           0
+#define USB_HUB_SINGLE_TT       1
+#define USB_HUB_MULTI_TT        2
+#define USB_HUB_SUPERSPEED      3
+
 // Hub requests
 #define USB_HUB_SET_DEPTH       12
 
diff --git a/system/ulib/ddk/include/ddk/protocol/usb-bus.h b/system/ulib/ddk/include/ddk/protocol/usb-bus.h
index 52291e9..658fdee 100644
--- a/system/ulib/ddk/include/ddk/protocol/usb-bus.h
+++ b/system/ulib/ddk/include/ddk/protocol/usb-bus.h
@@ -16,7 +16,7 @@
 typedef struct usb_bus_protocol_ops {
     // Hub support
     zx_status_t (*configure_hub)(void* ctx, zx_device_t* hub_device, usb_speed_t speed,
-                 usb_hub_descriptor_t* descriptor);
+                 bool multi_tt, usb_hub_descriptor_t* descriptor);
     zx_status_t (*hub_device_added)(void* ctx, zx_device_t* hub_device, int port,
                                     usb_speed_t speed);
     zx_status_t (*hub_device_removed)(void* ctx, zx_device_t* hub_device, int port);
@@ -28,9 +28,9 @@
 } usb_bus_protocol_t;
 
 static inline zx_status_t usb_bus_configure_hub(usb_bus_protocol_t* bus, zx_device_t* hub_device,
-                                                usb_speed_t speed,
+                                                usb_speed_t speed, bool multi_tt,
                                                 usb_hub_descriptor_t* descriptor) {
-    return bus->ops->configure_hub(bus->ctx, hub_device, speed, descriptor);
+    return bus->ops->configure_hub(bus->ctx, hub_device, speed, multi_tt, descriptor);
 }
 
 static inline zx_status_t usb_bus_hub_device_added(usb_bus_protocol_t* bus, zx_device_t* hub_device,
diff --git a/system/ulib/ddk/include/ddk/protocol/usb-hci.h b/system/ulib/ddk/include/ddk/protocol/usb-hci.h
index 9b3745d..31469a3 100644
--- a/system/ulib/ddk/include/ddk/protocol/usb-hci.h
+++ b/system/ulib/ddk/include/ddk/protocol/usb-hci.h
@@ -29,7 +29,7 @@
     uint64_t (*get_current_frame)(void* ctx);
 
     // Hub support
-    zx_status_t (*configure_hub)(void* ctx, uint32_t device_id, usb_speed_t speed,
+    zx_status_t (*configure_hub)(void* ctx, uint32_t device_id, usb_speed_t speed, bool multi_tt,
                  usb_hub_descriptor_t* descriptor);
     zx_status_t (*hub_device_added)(void* ctx, uint32_t device_id, int port, usb_speed_t speed);
     zx_status_t (*hub_device_removed)(void* ctx, uint32_t device_id, int port);
@@ -69,9 +69,9 @@
 }
 
 static inline zx_status_t usb_hci_configure_hub(usb_hci_protocol_t* hci, uint32_t device_id,
-                                                usb_speed_t speed,
+                                                usb_speed_t speed, bool multi_tt,
                                                 usb_hub_descriptor_t* descriptor) {
-    return hci->ops->configure_hub(hci->ctx, device_id, speed, descriptor);
+    return hci->ops->configure_hub(hci->ctx, device_id, speed, multi_tt, descriptor);
 }
 
 static inline zx_status_t usb_hci_hub_device_added(usb_hci_protocol_t* hci, uint32_t device_id,
diff --git a/system/ulib/ddk/include/ddk/protocol/usb.h b/system/ulib/ddk/include/ddk/protocol/usb.h
index 80f80af..e3fcdb0 100644
--- a/system/ulib/ddk/include/ddk/protocol/usb.h
+++ b/system/ulib/ddk/include/ddk/protocol/usb.h
@@ -24,6 +24,7 @@
     zx_status_t (*reset_endpoint)(void* ctx, uint8_t ep_address);
     size_t (*get_max_transfer_size)(void* ctx, uint8_t ep_address);
     uint32_t (*get_device_id)(void* ctx);
+    zx_status_t (*get_device_descriptor)(void* ctx, usb_device_descriptor_t* out_desc);
     zx_status_t (*get_descriptor_list)(void* ctx, void** out_descriptors, size_t* out_length);
     zx_status_t (*get_additional_descriptor_list)(void* ctx, void** out_descriptors,
                                                   size_t* out_length);
@@ -104,6 +105,11 @@
     return usb->ops->get_device_id(usb->ctx);
 }
 
+static inline zx_status_t usb_get_device_descriptor(usb_protocol_t* usb,
+                                                    usb_device_descriptor_t* out_desc) {
+    return usb->ops->get_device_descriptor(usb->ctx, out_desc);
+}
+
 // returns the USB descriptors for the USB device or interface
 // the returned value is de-allocated with free()
 static inline zx_status_t usb_get_descriptor_list(usb_protocol_t* usb, void** out_descriptors,