Browse Source

[xhci] Support USB1 devices attached via transaction translators

xHCI provides a somewhat convoluted mechanism for specifying details
of a transaction translator.  Hubs must be marked as such in the
device slot context.  The only opportunity to do so is as part of a
Configure Endpoint command, which can be executed only when opening
the hub's interrupt endpoint.

We add a mechanism for host controllers to intercept the opening of
hub devices, providing xHCI with an opportunity to update the internal
device slot structure for the corresponding USB device to indicate
that the device is a hub.  We then include the hub-specific details in
the input context whenever any Configure Endpoint command is issued.

When a device is opened, we record the device slot and port for its
transaction translator (if any), and supply these as part of the
Address Device command.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
f557794ab3
5 changed files with 164 additions and 33 deletions
  1. 18
    5
      src/drivers/bus/usb.c
  2. 46
    13
      src/drivers/usb/ehci.c
  3. 73
    13
      src/drivers/usb/xhci.c
  4. 6
    0
      src/drivers/usb/xhci.h
  5. 21
    2
      src/include/ipxe/usb.h

+ 18
- 5
src/drivers/bus/usb.c View File

1692
 		hub->protocol = usb->port->protocol;
1692
 		hub->protocol = usb->port->protocol;
1693
 	hub->ports = ports;
1693
 	hub->ports = ports;
1694
 	hub->driver = driver;
1694
 	hub->driver = driver;
1695
+	hub->host = &bus->op->hub;
1695
 
1696
 
1696
 	/* Initialise port list */
1697
 	/* Initialise port list */
1697
 	for ( i = 1 ; i <= hub->ports ; i++ ) {
1698
 	for ( i = 1 ; i <= hub->ports ; i++ ) {
1721
 	/* Add to hub list */
1722
 	/* Add to hub list */
1722
 	list_add_tail ( &hub->list, &bus->hubs );
1723
 	list_add_tail ( &hub->list, &bus->hubs );
1723
 
1724
 
1724
-	/* Open hub */
1725
+	/* Open hub (host controller) */
1726
+	if ( ( rc = hub->host->open ( hub ) ) != 0 ) {
1727
+		DBGC ( hub, "USB hub %s could not open: %s\n",
1728
+		       hub->name, strerror ( rc ) );
1729
+		goto err_host_open;
1730
+	}
1731
+
1732
+	/* Open hub (driver) */
1725
 	if ( ( rc = hub->driver->open ( hub ) ) != 0 ) {
1733
 	if ( ( rc = hub->driver->open ( hub ) ) != 0 ) {
1726
 		DBGC ( hub, "USB hub %s could not open: %s\n",
1734
 		DBGC ( hub, "USB hub %s could not open: %s\n",
1727
 		       hub->name, strerror ( rc ) );
1735
 		       hub->name, strerror ( rc ) );
1728
-		goto err_open;
1736
+		goto err_driver_open;
1729
 	}
1737
 	}
1730
 
1738
 
1731
 	/* Delay to allow ports to stabilise */
1739
 	/* Delay to allow ports to stabilise */
1747
 	return 0;
1755
 	return 0;
1748
 
1756
 
1749
 	hub->driver->close ( hub );
1757
 	hub->driver->close ( hub );
1750
- err_open:
1758
+ err_driver_open:
1759
+	hub->host->close ( hub );
1760
+ err_host_open:
1751
 	list_del ( &hub->list );
1761
 	list_del ( &hub->list );
1752
 	return rc;
1762
 	return rc;
1753
 }
1763
 }
1768
 			usb_detached ( port );
1778
 			usb_detached ( port );
1769
 	}
1779
 	}
1770
 
1780
 
1771
-	/* Close hub */
1781
+	/* Close hub (driver) */
1772
 	hub->driver->close ( hub );
1782
 	hub->driver->close ( hub );
1773
 
1783
 
1784
+	/* Close hub (host controller) */
1785
+	hub->host->close ( hub );
1786
+
1774
 	/* Cancel any pending port status changes */
1787
 	/* Cancel any pending port status changes */
1775
 	for ( i = 1 ; i <= hub->ports ; i++ ) {
1788
 	for ( i = 1 ; i <= hub->ports ; i++ ) {
1776
 		port = usb_port ( hub, i );
1789
 		port = usb_port ( hub, i );
1839
 	bus->host = &bus->op->bus;
1852
 	bus->host = &bus->op->bus;
1840
 
1853
 
1841
 	/* Allocate root hub */
1854
 	/* Allocate root hub */
1842
-	bus->hub = alloc_usb_hub ( bus, NULL, ports, &op->hub );
1855
+	bus->hub = alloc_usb_hub ( bus, NULL, ports, &op->root );
1843
 	if ( ! bus->hub )
1856
 	if ( ! bus->hub )
1844
 		goto err_alloc_hub;
1857
 		goto err_alloc_hub;
1845
 
1858
 

+ 46
- 13
src/drivers/usb/ehci.c View File

1330
 	return rc;
1330
 	return rc;
1331
 }
1331
 }
1332
 
1332
 
1333
+/******************************************************************************
1334
+ *
1335
+ * Hub operations
1336
+ *
1337
+ ******************************************************************************
1338
+ */
1339
+
1340
+/**
1341
+ * Open hub
1342
+ *
1343
+ * @v hub		USB hub
1344
+ * @ret rc		Return status code
1345
+ */
1346
+static int ehci_hub_open ( struct usb_hub *hub __unused ) {
1347
+
1348
+	/* Nothing to do */
1349
+	return 0;
1350
+}
1351
+
1352
+/**
1353
+ * Close hub
1354
+ *
1355
+ * @v hub		USB hub
1356
+ */
1357
+static void ehci_hub_close ( struct usb_hub *hub __unused ) {
1358
+
1359
+	/* Nothing to do */
1360
+}
1361
+
1333
 /******************************************************************************
1362
 /******************************************************************************
1334
  *
1363
  *
1335
  * Root hub operations
1364
  * Root hub operations
1343
  * @v hub		USB hub
1372
  * @v hub		USB hub
1344
  * @ret rc		Return status code
1373
  * @ret rc		Return status code
1345
  */
1374
  */
1346
-static int ehci_hub_open ( struct usb_hub *hub ) {
1375
+static int ehci_root_open ( struct usb_hub *hub ) {
1347
 	struct usb_bus *bus = hub->bus;
1376
 	struct usb_bus *bus = hub->bus;
1348
 	struct ehci_device *ehci = usb_bus_get_hostdata ( bus );
1377
 	struct ehci_device *ehci = usb_bus_get_hostdata ( bus );
1349
 	uint32_t portsc;
1378
 	uint32_t portsc;
1374
  *
1403
  *
1375
  * @v hub		USB hub
1404
  * @v hub		USB hub
1376
  */
1405
  */
1377
-static void ehci_hub_close ( struct usb_hub *hub ) {
1406
+static void ehci_root_close ( struct usb_hub *hub ) {
1378
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1407
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1379
 
1408
 
1380
 	/* Route all ports back to companion controllers */
1409
 	/* Route all ports back to companion controllers */
1391
  * @v port		USB port
1420
  * @v port		USB port
1392
  * @ret rc		Return status code
1421
  * @ret rc		Return status code
1393
  */
1422
  */
1394
-static int ehci_hub_enable ( struct usb_hub *hub, struct usb_port *port ) {
1423
+static int ehci_root_enable ( struct usb_hub *hub, struct usb_port *port ) {
1395
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1424
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1396
 	uint32_t portsc;
1425
 	uint32_t portsc;
1397
 	unsigned int line;
1426
 	unsigned int line;
1449
  * @v port		USB port
1478
  * @v port		USB port
1450
  * @ret rc		Return status code
1479
  * @ret rc		Return status code
1451
  */
1480
  */
1452
-static int ehci_hub_disable ( struct usb_hub *hub, struct usb_port *port ) {
1481
+static int ehci_root_disable ( struct usb_hub *hub, struct usb_port *port ) {
1453
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1482
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1454
 	uint32_t portsc;
1483
 	uint32_t portsc;
1455
 
1484
 
1468
  * @v port		USB port
1497
  * @v port		USB port
1469
  * @ret rc		Return status code
1498
  * @ret rc		Return status code
1470
  */
1499
  */
1471
-static int ehci_hub_speed ( struct usb_hub *hub, struct usb_port *port ) {
1500
+static int ehci_root_speed ( struct usb_hub *hub, struct usb_port *port ) {
1472
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1501
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1473
 	uint32_t portsc;
1502
 	uint32_t portsc;
1474
 	unsigned int speed;
1503
 	unsigned int speed;
1512
  * @v ep		USB endpoint
1541
  * @v ep		USB endpoint
1513
  * @ret rc		Return status code
1542
  * @ret rc		Return status code
1514
  */
1543
  */
1515
-static int ehci_hub_clear_tt ( struct usb_hub *hub, struct usb_port *port,
1516
-			       struct usb_endpoint *ep ) {
1544
+static int ehci_root_clear_tt ( struct usb_hub *hub, struct usb_port *port,
1545
+				struct usb_endpoint *ep ) {
1517
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1546
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1518
 
1547
 
1519
 	/* Should never be called; this is a root hub */
1548
 	/* Should never be called; this is a root hub */
1529
  * @v hub		USB hub
1558
  * @v hub		USB hub
1530
  * @v port		USB port
1559
  * @v port		USB port
1531
  */
1560
  */
1532
-static void ehci_hub_poll ( struct usb_hub *hub, struct usb_port *port ) {
1561
+static void ehci_root_poll ( struct usb_hub *hub, struct usb_port *port ) {
1533
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1562
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
1534
 	uint32_t portsc;
1563
 	uint32_t portsc;
1535
 	uint32_t change;
1564
 	uint32_t change;
1692
 
1721
 
1693
 		/* Iterate over all ports looking for status changes */
1722
 		/* Iterate over all ports looking for status changes */
1694
 		for ( i = 1 ; i <= ehci->ports ; i++ )
1723
 		for ( i = 1 ; i <= ehci->ports ; i++ )
1695
-			ehci_hub_poll ( hub, usb_port ( hub, i ) );
1724
+			ehci_root_poll ( hub, usb_port ( hub, i ) );
1696
 	}
1725
 	}
1697
 
1726
 
1698
 	/* Report fatal errors */
1727
 	/* Report fatal errors */
1730
 	.hub = {
1759
 	.hub = {
1731
 		.open = ehci_hub_open,
1760
 		.open = ehci_hub_open,
1732
 		.close = ehci_hub_close,
1761
 		.close = ehci_hub_close,
1733
-		.enable = ehci_hub_enable,
1734
-		.disable = ehci_hub_disable,
1735
-		.speed = ehci_hub_speed,
1736
-		.clear_tt = ehci_hub_clear_tt,
1762
+	},
1763
+	.root = {
1764
+		.open = ehci_root_open,
1765
+		.close = ehci_root_close,
1766
+		.enable = ehci_root_enable,
1767
+		.disable = ehci_root_disable,
1768
+		.speed = ehci_root_speed,
1769
+		.clear_tt = ehci_root_clear_tt,
1737
 	},
1770
 	},
1738
 };
1771
 };
1739
 
1772
 

+ 73
- 13
src/drivers/usb/xhci.c View File

1990
 	slot_ctx->info = cpu_to_le32 ( XHCI_SLOT_INFO ( 1, 0, slot->psiv,
1990
 	slot_ctx->info = cpu_to_le32 ( XHCI_SLOT_INFO ( 1, 0, slot->psiv,
1991
 							slot->route ) );
1991
 							slot->route ) );
1992
 	slot_ctx->port = slot->port;
1992
 	slot_ctx->port = slot->port;
1993
+	slot_ctx->tt_id = slot->tt_id;
1994
+	slot_ctx->tt_port = slot->tt_port;
1993
 
1995
 
1994
 	/* Populate control endpoint context */
1996
 	/* Populate control endpoint context */
1995
 	ep_ctx = ( input + xhci_input_context_offset ( xhci, XHCI_CTX_EP0 ) );
1997
 	ep_ctx = ( input + xhci_input_context_offset ( xhci, XHCI_CTX_EP0 ) );
2039
  * @v input		Input context
2041
  * @v input		Input context
2040
  */
2042
  */
2041
 static void xhci_configure_endpoint_input ( struct xhci_device *xhci,
2043
 static void xhci_configure_endpoint_input ( struct xhci_device *xhci,
2042
-					    struct xhci_slot *slot __unused,
2044
+					    struct xhci_slot *slot,
2043
 					    struct xhci_endpoint *endpoint,
2045
 					    struct xhci_endpoint *endpoint,
2044
 					    void *input ) {
2046
 					    void *input ) {
2045
 	struct xhci_control_context *control_ctx;
2047
 	struct xhci_control_context *control_ctx;
2054
 	/* Populate slot context */
2056
 	/* Populate slot context */
2055
 	slot_ctx = ( input + xhci_input_context_offset ( xhci, XHCI_CTX_SLOT ));
2057
 	slot_ctx = ( input + xhci_input_context_offset ( xhci, XHCI_CTX_SLOT ));
2056
 	slot_ctx->info = cpu_to_le32 ( XHCI_SLOT_INFO ( ( XHCI_CTX_END - 1 ),
2058
 	slot_ctx->info = cpu_to_le32 ( XHCI_SLOT_INFO ( ( XHCI_CTX_END - 1 ),
2057
-							0, 0, 0 ) );
2059
+							( slot->ports ? 1 : 0 ),
2060
+							slot->psiv, 0 ) );
2061
+	slot_ctx->ports = slot->ports;
2058
 
2062
 
2059
 	/* Populate endpoint context */
2063
 	/* Populate endpoint context */
2060
 	ep_ctx = ( input + xhci_input_context_offset ( xhci, endpoint->ctx ) );
2064
 	ep_ctx = ( input + xhci_input_context_offset ( xhci, endpoint->ctx ) );
2587
  */
2591
  */
2588
 static int xhci_device_open ( struct usb_device *usb ) {
2592
 static int xhci_device_open ( struct usb_device *usb ) {
2589
 	struct xhci_device *xhci = usb_bus_get_hostdata ( usb->port->hub->bus );
2593
 	struct xhci_device *xhci = usb_bus_get_hostdata ( usb->port->hub->bus );
2594
+	struct usb_port *tt = usb_transaction_translator ( usb );
2590
 	struct xhci_slot *slot;
2595
 	struct xhci_slot *slot;
2596
+	struct xhci_slot *tt_slot;
2591
 	size_t len;
2597
 	size_t len;
2592
 	int type;
2598
 	int type;
2593
 	int id;
2599
 	int id;
2621
 	slot->xhci = xhci;
2627
 	slot->xhci = xhci;
2622
 	slot->usb = usb;
2628
 	slot->usb = usb;
2623
 	slot->id = id;
2629
 	slot->id = id;
2630
+	if ( tt ) {
2631
+		tt_slot = usb_get_hostdata ( tt->hub->usb );
2632
+		slot->tt_id = tt_slot->id;
2633
+		slot->tt_port = tt->address;
2634
+	}
2624
 
2635
 
2625
 	/* Allocate a device context */
2636
 	/* Allocate a device context */
2626
 	len = xhci_device_context_offset ( xhci, XHCI_CTX_END );
2637
 	len = xhci_device_context_offset ( xhci, XHCI_CTX_END );
2817
 	xhci_event_poll ( xhci );
2828
 	xhci_event_poll ( xhci );
2818
 }
2829
 }
2819
 
2830
 
2831
+/******************************************************************************
2832
+ *
2833
+ * Hub operations
2834
+ *
2835
+ ******************************************************************************
2836
+ */
2837
+
2838
+/**
2839
+ * Open hub
2840
+ *
2841
+ * @v hub		USB hub
2842
+ * @ret rc		Return status code
2843
+ */
2844
+static int xhci_hub_open ( struct usb_hub *hub ) {
2845
+	struct xhci_slot *slot;
2846
+
2847
+	/* Do nothing if this is the root hub */
2848
+	if ( ! hub->usb )
2849
+		return 0;
2850
+
2851
+	/* Get device slot */
2852
+	slot = usb_get_hostdata ( hub->usb );
2853
+
2854
+	/* Update device slot hub parameters.  We don't inform the
2855
+	 * hardware of this information until the hub's interrupt
2856
+	 * endpoint is opened, since the only mechanism for so doing
2857
+	 * provided by the xHCI specification is a Configure Endpoint
2858
+	 * command, and we can't issue that command until we have a
2859
+	 * non-EP0 endpoint to configure.
2860
+	 */
2861
+	slot->ports = hub->ports;
2862
+
2863
+	return 0;
2864
+}
2865
+
2866
+/**
2867
+ * Close hub
2868
+ *
2869
+ * @v hub		USB hub
2870
+ */
2871
+static void xhci_hub_close ( struct usb_hub *hub __unused ) {
2872
+
2873
+	/* Nothing to do */
2874
+}
2875
+
2820
 /******************************************************************************
2876
 /******************************************************************************
2821
  *
2877
  *
2822
  * Root hub operations
2878
  * Root hub operations
2830
  * @v hub		USB hub
2886
  * @v hub		USB hub
2831
  * @ret rc		Return status code
2887
  * @ret rc		Return status code
2832
  */
2888
  */
2833
-static int xhci_hub_open ( struct usb_hub *hub ) {
2889
+static int xhci_root_open ( struct usb_hub *hub ) {
2834
 	struct usb_bus *bus = hub->bus;
2890
 	struct usb_bus *bus = hub->bus;
2835
 	struct xhci_device *xhci = usb_bus_get_hostdata ( bus );
2891
 	struct xhci_device *xhci = usb_bus_get_hostdata ( bus );
2836
 	struct usb_port *port;
2892
 	struct usb_port *port;
2880
  *
2936
  *
2881
  * @v hub		USB hub
2937
  * @v hub		USB hub
2882
  */
2938
  */
2883
-static void xhci_hub_close ( struct usb_hub *hub ) {
2939
+static void xhci_root_close ( struct usb_hub *hub ) {
2884
 
2940
 
2885
 	/* Clear hub driver private data */
2941
 	/* Clear hub driver private data */
2886
 	usb_hub_set_drvdata ( hub, NULL );
2942
 	usb_hub_set_drvdata ( hub, NULL );
2893
  * @v port		USB port
2949
  * @v port		USB port
2894
  * @ret rc		Return status code
2950
  * @ret rc		Return status code
2895
  */
2951
  */
2896
-static int xhci_hub_enable ( struct usb_hub *hub, struct usb_port *port ) {
2952
+static int xhci_root_enable ( struct usb_hub *hub, struct usb_port *port ) {
2897
 	struct xhci_device *xhci = usb_hub_get_drvdata ( hub );
2953
 	struct xhci_device *xhci = usb_hub_get_drvdata ( hub );
2898
 	uint32_t portsc;
2954
 	uint32_t portsc;
2899
 	unsigned int i;
2955
 	unsigned int i;
2930
  * @v port		USB port
2986
  * @v port		USB port
2931
  * @ret rc		Return status code
2987
  * @ret rc		Return status code
2932
  */
2988
  */
2933
-static int xhci_hub_disable ( struct usb_hub *hub, struct usb_port *port ) {
2989
+static int xhci_root_disable ( struct usb_hub *hub, struct usb_port *port ) {
2934
 	struct xhci_device *xhci = usb_hub_get_drvdata ( hub );
2990
 	struct xhci_device *xhci = usb_hub_get_drvdata ( hub );
2935
 	uint32_t portsc;
2991
 	uint32_t portsc;
2936
 
2992
 
2950
  * @v port		USB port
3006
  * @v port		USB port
2951
  * @ret rc		Return status code
3007
  * @ret rc		Return status code
2952
  */
3008
  */
2953
-static int xhci_hub_speed ( struct usb_hub *hub, struct usb_port *port ) {
3009
+static int xhci_root_speed ( struct usb_hub *hub, struct usb_port *port ) {
2954
 	struct xhci_device *xhci = usb_hub_get_drvdata ( hub );
3010
 	struct xhci_device *xhci = usb_hub_get_drvdata ( hub );
2955
 	uint32_t portsc;
3011
 	uint32_t portsc;
2956
 	unsigned int psiv;
3012
 	unsigned int psiv;
3000
  * @v ep		USB endpoint
3056
  * @v ep		USB endpoint
3001
  * @ret rc		Return status code
3057
  * @ret rc		Return status code
3002
  */
3058
  */
3003
-static int xhci_hub_clear_tt ( struct usb_hub *hub, struct usb_port *port,
3004
-			       struct usb_endpoint *ep ) {
3059
+static int xhci_root_clear_tt ( struct usb_hub *hub, struct usb_port *port,
3060
+				struct usb_endpoint *ep ) {
3005
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
3061
 	struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
3006
 
3062
 
3007
 	/* Should never be called; this is a root hub */
3063
 	/* Should never be called; this is a root hub */
3041
 	.hub = {
3097
 	.hub = {
3042
 		.open = xhci_hub_open,
3098
 		.open = xhci_hub_open,
3043
 		.close = xhci_hub_close,
3099
 		.close = xhci_hub_close,
3044
-		.enable = xhci_hub_enable,
3045
-		.disable = xhci_hub_disable,
3046
-		.speed = xhci_hub_speed,
3047
-		.clear_tt = xhci_hub_clear_tt,
3100
+	},
3101
+	.root = {
3102
+		.open = xhci_root_open,
3103
+		.close = xhci_root_close,
3104
+		.enable = xhci_root_enable,
3105
+		.disable = xhci_root_disable,
3106
+		.speed = xhci_root_speed,
3107
+		.clear_tt = xhci_root_clear_tt,
3048
 	},
3108
 	},
3049
 };
3109
 };
3050
 
3110
 

+ 6
- 0
src/drivers/usb/xhci.h View File

1110
 	unsigned int port;
1110
 	unsigned int port;
1111
 	/** Protocol speed ID */
1111
 	/** Protocol speed ID */
1112
 	unsigned int psiv;
1112
 	unsigned int psiv;
1113
+	/** Number of ports (if this device is a hub) */
1114
+	unsigned int ports;
1115
+	/** Transaction translator slot ID */
1116
+	unsigned int tt_id;
1117
+	/** Transaction translator port */
1118
+	unsigned int tt_port;
1113
 	/** Endpoints, indexed by context ID */
1119
 	/** Endpoints, indexed by context ID */
1114
 	struct xhci_endpoint *endpoint[XHCI_CTX_END];
1120
 	struct xhci_endpoint *endpoint[XHCI_CTX_END];
1115
 };
1121
 };

+ 21
- 2
src/include/ipxe/usb.h View File

777
 	/** List of hubs */
777
 	/** List of hubs */
778
 	struct list_head list;
778
 	struct list_head list;
779
 
779
 
780
+	/** Host controller operations */
781
+	struct usb_hub_host_operations *host;
780
 	/** Driver operations */
782
 	/** Driver operations */
781
 	struct usb_hub_driver_operations *driver;
783
 	struct usb_hub_driver_operations *driver;
782
 	/** Driver private data */
784
 	/** Driver private data */
789
 	struct usb_port port[0];
791
 	struct usb_port port[0];
790
 };
792
 };
791
 
793
 
792
-/** USB hub operations */
794
+/** USB hub host controller operations */
795
+struct usb_hub_host_operations {
796
+	/** Open hub
797
+	 *
798
+	 * @v hub		USB hub
799
+	 * @ret rc		Return status code
800
+	 */
801
+	int ( * open ) ( struct usb_hub *hub );
802
+	/** Close hub
803
+	 *
804
+	 * @v hub		USB hub
805
+	 */
806
+	void ( * close ) ( struct usb_hub *hub );
807
+};
808
+
809
+/** USB hub driver operations */
793
 struct usb_hub_driver_operations {
810
 struct usb_hub_driver_operations {
794
 	/** Open hub
811
 	/** Open hub
795
 	 *
812
 	 *
940
 	struct usb_device_host_operations device;
957
 	struct usb_device_host_operations device;
941
 	/** Bus operations */
958
 	/** Bus operations */
942
 	struct usb_bus_host_operations bus;
959
 	struct usb_bus_host_operations bus;
960
+	/** Hub operations */
961
+	struct usb_hub_host_operations hub;
943
 	/** Root hub operations */
962
 	/** Root hub operations */
944
-	struct usb_hub_driver_operations hub;
963
+	struct usb_hub_driver_operations root;
945
 };
964
 };
946
 
965
 
947
 /**
966
 /**

Loading…
Cancel
Save