Index: uspace/drv/block/usbmast/main.c
===================================================================
--- uspace/drv/block/usbmast/main.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/block/usbmast/main.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -172,7 +172,7 @@
 	    usb_device_get_name(dev));
 	usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
-	    epm_in->pipe.desc.endpoint_no, epm_in->pipe.desc.max_packet_size);
+	    epm_in->pipe.desc.endpoint_no, epm_in->pipe.desc.max_transfer_size);
 	usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
-	    epm_out->pipe.desc.endpoint_no, epm_out->pipe.desc.max_packet_size);
+	    epm_out->pipe.desc.endpoint_no, epm_out->pipe.desc.max_transfer_size);
 
 	usb_log_debug("Get LUN count...\n");
Index: uspace/drv/bus/usb/ehci/ehci_bus.c
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_bus.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -78,5 +78,5 @@
 /** Creates new hcd endpoint representation.
  */
-static endpoint_t *ehci_endpoint_create(device_t *dev, const usb_endpoint_desc_t *desc)
+static endpoint_t *ehci_endpoint_create(device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
 	assert(dev);
Index: uspace/drv/bus/usb/ehci/hw_struct/queue_head.c
===================================================================
--- uspace/drv/bus/usb/ehci/hw_struct/queue_head.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/bus/usb/ehci/hw_struct/queue_head.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -82,5 +82,5 @@
 	}
 	uint32_t ep_cap = QH_EP_CAP_C_MASK_SET(3 << 2) |
-		    QH_EP_CAP_MULTI_SET(ep->packets);
+		    QH_EP_CAP_MULTI_SET(ep->packets_per_uframe);
 	if (ep->device->speed != USB_SPEED_HIGH) {
 		ep_cap |=
Index: uspace/drv/bus/usb/ohci/ohci_bus.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_bus.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -72,5 +72,5 @@
 /** Creates new hcd endpoint representation.
  */
-static endpoint_t *ohci_endpoint_create(device_t *dev, const usb_endpoint_desc_t *desc)
+static endpoint_t *ohci_endpoint_create(device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
 	assert(dev);
Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -51,13 +51,9 @@
 
 /** Initial descriptor used for control endpoint 0 before more configuration is retrieved. */
-static const usb_endpoint_desc_t ep0_initial_desc = {
-	.endpoint_no = 0,
-	.direction = USB_DIRECTION_BOTH,
-	.transfer_type = USB_TRANSFER_CONTROL,
-	.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
-	.packets = 1,
+static const usb_endpoint_descriptors_t ep0_initial_desc = {
+	.endpoint.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
 };
 
-static endpoint_t *endpoint_create(device_t *, const usb_endpoint_desc_t *);
+static endpoint_t *endpoint_create(device_t *, const usb_endpoint_descriptors_t *);
 
 /** Assign address and control endpoint to a new XHCI device.
@@ -368,5 +364,5 @@
 }
 
-static endpoint_t *endpoint_create(device_t *dev, const usb_endpoint_desc_t *desc)
+static endpoint_t *endpoint_create(device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
 	xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t));
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -52,5 +52,5 @@
  * @return Error code.
  */
-int xhci_endpoint_init(xhci_endpoint_t *xhci_ep, device_t *dev, const usb_endpoint_desc_t *desc)
+int xhci_endpoint_init(xhci_endpoint_t *xhci_ep, device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
 	assert(xhci_ep);
@@ -60,15 +60,28 @@
 	endpoint_init(ep, dev, desc);
 
-	xhci_ep->max_streams = desc->usb3.max_streams;
-	xhci_ep->max_burst = desc->usb3.max_burst;
-	xhci_ep->mult = desc->usb3.mult;
-
-	// TODO: process according to 6.2.3.6 of XHCI specification; hardcoded for HS/SS EPs
-	xhci_ep->interval = desc->interval - 1;
+	xhci_ep->max_streams = USB_SSC_MAX_STREAMS(desc->companion);
+	xhci_ep->max_burst = desc->companion.max_burst + 1;
+	xhci_ep->mult = USB_SSC_MULT(desc->companion) + 1;
+
+	/* In USB 3, the semantics of wMaxPacketSize changed. Now the number of
+	 * packets per service interval is determined from max_burst and mult.
+	 */
+	if (dev->speed >= USB_SPEED_SUPER) {
+		ep->packets_per_uframe = xhci_ep->max_burst * xhci_ep->mult;
+		ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
+	}
+
+	xhci_ep->interval = desc->endpoint.poll_interval;
+	/* Only Low/Full speed interrupt endpoints have interval set directly,
+	 * others have 2-based log of it.
+	 */
+	if (dev->speed >= USB_SPEED_HIGH || ep->transfer_type != USB_TRANSFER_INTERRUPT) {
+		xhci_ep->interval = 1 << (xhci_ep->interval - 1);
+	}
 
 	if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
-		xhci_ep->isoch_max_size = desc->usb3.bytes_per_interval
-			? desc->usb3.bytes_per_interval
-			: desc->max_packet_size * (desc->packets + 1);
+		xhci_ep->isoch_max_size = desc->companion.bytes_per_interval
+			? desc->companion.bytes_per_interval
+			: ep->max_transfer_size;
 		/* Technically there could be superspeed plus too. */
 
@@ -497,6 +510,4 @@
 	dev->endpoints[ep->base.endpoint] = NULL;
 	ep->base.device = NULL;
-
-	endpoint_del_ref(&ep->base);
 }
 
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -149,5 +149,5 @@
 #define XHCI_DEV_ARGS(dev)		 ddf_fun_get_name((dev).base.fun), (dev).slot_id
 
-int xhci_endpoint_init(xhci_endpoint_t *, device_t *, const usb_endpoint_desc_t *);
+int xhci_endpoint_init(xhci_endpoint_t *, device_t *, const usb_endpoint_descriptors_t *);
 void xhci_endpoint_fini(xhci_endpoint_t *);
 int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *);
Index: uspace/drv/hid/usbhid/main.c
===================================================================
--- uspace/drv/hid/usbhid/main.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/drv/hid/usbhid/main.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -95,5 +95,5 @@
 	   usb_hid_polling_callback,
 	   /* How much data to request. */
-	   hid_dev->poll_pipe_mapping->pipe.desc.max_packet_size,
+	   hid_dev->poll_pipe_mapping->pipe.desc.max_transfer_size,
 	   /* Delay */
 	   -1,
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -116,15 +116,12 @@
 }
 
-int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
-typedef union {
-	uint8_t arr[sizeof(sysarg_t)];
-	sysarg_t arg;
-} pack8_t;
-
-int usbhc_register_endpoint(async_exch_t *exch,
-	usb_endpoint_desc_t *endpoint_desc)
-{
-	if (!exch)
-		return EBADMEM;
+int usbhc_register_endpoint(async_exch_t *exch, usb_pipe_desc_t *pipe_desc,
+    const usb_endpoint_descriptors_t *desc)
+{
+	if (!exch)
+		return EBADMEM;
+
+	if (!desc)
+		return EINVAL;
 
 	aid_t opening_request = async_send_1(exch,
@@ -135,7 +132,5 @@
 	}
 
-	const int ret = async_data_write_start(exch, (void *) endpoint_desc,
-		sizeof(usb_endpoint_desc_t));
-
+	int ret = async_data_write_start(exch, desc, sizeof(*desc));
 	if (ret != EOK) {
 		async_forget(opening_request);
@@ -147,9 +142,20 @@
 	async_wait_for(opening_request, &opening_request_rc);
 
-	return (int) opening_request_rc;
-}
-
-int usbhc_unregister_endpoint(async_exch_t *exch,
-	usb_endpoint_desc_t *endpoint_desc)
+	if (opening_request_rc)
+		return (int) opening_request_rc;
+
+	usb_pipe_desc_t dest;
+	ret = async_data_read_start(exch, &dest, sizeof(dest));
+	if (ret != EOK) {
+		return ret;
+	}
+
+	if (pipe_desc)
+		*pipe_desc = dest;
+
+	return EOK;
+}
+
+int usbhc_unregister_endpoint(async_exch_t *exch, const usb_pipe_desc_t *pipe_desc)
 {
 	if (!exch)
@@ -163,6 +169,5 @@
 	}
 
-	const int ret = async_data_write_start(exch, endpoint_desc,
-		sizeof(usb_endpoint_desc_t));
+	const int ret = async_data_write_start(exch, pipe_desc, sizeof(*pipe_desc));
 	if (ret != EOK) {
 		async_forget(opening_request);
@@ -368,20 +373,25 @@
 	}
 
-	void *buffer = NULL;
-	size_t size = 0;
-	int rc = async_data_write_accept(&buffer, false,
-		sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);
-
-	if (rc != EOK) {
-		free(buffer);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
-	rc = usbhc_iface->register_endpoint(fun, endpoint_desc);
-
-	free(buffer);
+	usb_endpoint_descriptors_t ep_desc;
+	ipc_callid_t data_callid;
+	size_t len;
+
+	if (!async_data_write_receive(&data_callid, &len)
+	    || len != sizeof(ep_desc)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	async_data_write_finalize(data_callid, &ep_desc, sizeof(ep_desc));
+
+	usb_pipe_desc_t pipe_desc;
+
+	const int rc = usbhc_iface->register_endpoint(fun, &pipe_desc, &ep_desc);
 	async_answer_0(callid, rc);
+
+	if (!async_data_read_receive(&data_callid, &len)
+	    || len != sizeof(pipe_desc)) {
+		return;
+	}
+	async_data_read_finalize(data_callid, &pipe_desc, sizeof(pipe_desc));
 }
 
@@ -400,19 +410,16 @@
 	}
 
-	void *buffer = NULL;
-	size_t size = 0;
-	int rc = async_data_write_accept(&buffer, false,
-		sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size);
-
-	if (rc != EOK) {
-		free(buffer);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer;
-	usbhc_iface->unregister_endpoint(fun, endpoint_desc);
-
-	free(buffer);
+	usb_pipe_desc_t pipe_desc;
+	ipc_callid_t data_callid;
+	size_t len;
+
+	if (!async_data_write_receive(&data_callid, &len)
+	    || len != sizeof(pipe_desc)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	async_data_write_finalize(data_callid, &pipe_desc, sizeof(pipe_desc));
+
+	const int rc = usbhc_iface->unregister_endpoint(fun, &pipe_desc);
 	async_answer_0(callid, rc);
 }
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/drv/include/usb_iface.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -100,38 +100,4 @@
 } usb_target_t;
 
-/** Description of an usb endpoint.
- */
-typedef struct {
-	unsigned max_burst;
-	unsigned max_streams;
-	unsigned mult;
-	unsigned bytes_per_interval;
-} usb3_endpoint_desc_t;
-
-typedef struct usb_endpoint_desc {
-	/** Endpoint number. */
-	usb_endpoint_t endpoint_no;
-
-	/** Endpoint transfer type. */
-	usb_transfer_type_t transfer_type;
-
-	/** Endpoint direction. */
-	usb_direction_t direction;
-
-	/** Maximum packet size for the endpoint. */
-	size_t max_packet_size;
-
-	/** Scheduling interval for HC. Only valid for interrupt/isoch transfer. */
-	size_t interval;
-
-	/** Number of packets per frame/uframe.
-	 * Only valid for HS INT and ISO transfers. All others should set to 1*/
-	unsigned packets;
-
-	/** Superspeed-specific information */
-	usb3_endpoint_desc_t usb3;
-} usb_endpoint_desc_t;
-
-
 extern usb_dev_session_t *usb_dev_connect(devman_handle_t);
 extern usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *);
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -44,4 +44,40 @@
 #include <async.h>
 
+typedef struct usb_pipe_desc {
+	/** Endpoint number. */
+	usb_endpoint_t endpoint_no;
+
+	/** Endpoint transfer type. */
+	usb_transfer_type_t transfer_type;
+
+	/** Endpoint direction. */
+	usb_direction_t direction;
+
+	/** Maximum size of one transfer */
+	size_t max_transfer_size;
+} usb_pipe_desc_t;
+
+/** This structure follows standard endpoint descriptor + superspeed companion
+ * descriptor, and exists to avoid dependency of libdrv on libusb. Keep the
+ * internal fields named exactly like their source (because we want to use the
+ * same macros to access them).
+ * Callers shall fill it with bare contents of respective descriptors (in usb endianity).
+ */
+typedef struct {
+	struct {
+		uint8_t endpoint_address;
+		uint8_t attributes;
+		uint16_t max_packet_size;
+		uint8_t poll_interval;
+	} endpoint;
+
+	/* Superspeed companion descriptor */
+	struct companion_desc_t {
+		uint8_t max_burst;
+		uint8_t attributes;
+		uint16_t bytes_per_interval;
+	} companion;
+} usb_endpoint_descriptors_t;
+
 extern int usbhc_reserve_default_address(async_exch_t *, usb_speed_t);
 extern int usbhc_release_default_address(async_exch_t *);
@@ -50,6 +86,7 @@
 extern int usbhc_device_remove(async_exch_t *, unsigned port);
 
-extern int usbhc_register_endpoint(async_exch_t *, usb_endpoint_desc_t *);
-extern int usbhc_unregister_endpoint(async_exch_t *, usb_endpoint_desc_t *);
+extern int usbhc_register_endpoint(async_exch_t *, usb_pipe_desc_t *, const usb_endpoint_descriptors_t *);
+extern int usbhc_unregister_endpoint(async_exch_t *, const usb_pipe_desc_t *);
+
 extern int usbhc_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t,
     size_t *);
@@ -68,6 +105,6 @@
 	int (*device_remove)(ddf_fun_t *, unsigned);
 
-	int (*register_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *);
-	int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *);
+	int (*register_endpoint)(ddf_fun_t *, usb_pipe_desc_t *, const usb_endpoint_descriptors_t *);
+	int (*unregister_endpoint)(ddf_fun_t *, const usb_pipe_desc_t *);
 
 	int (*read)(ddf_fun_t *, usb_target_t,
Index: uspace/lib/usb/include/usb/descriptor.h
===================================================================
--- uspace/lib/usb/include/usb/descriptor.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usb/include/usb/descriptor.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -200,8 +200,12 @@
 	/** Endpoint address together with data flow direction. */
 	uint8_t endpoint_address;
+#define USB_ED_GET_EP(ed)	((ed).endpoint_address & 0xf)
+#define USB_ED_GET_DIR(ed)	(!(((ed).endpoint_address >> 7) & 0x1))
+
 	/** Endpoint attributes.
 	 * Includes transfer type (usb_transfer_type_t).
 	 */
 	uint8_t attributes;
+#define USB_ED_GET_TRANSFER_TYPE(ed)	((ed).attributes & 0x3)
 	/** Maximum packet size.
 	 * Lower 10 bits represent the actuall size
@@ -209,11 +213,8 @@
 	 * HS INT and ISO transfers. */
 	uint16_t max_packet_size;
-
-#define ED_MPS_PACKET_SIZE_MASK  0x3ff
-#define ED_MPS_PACKET_SIZE_GET(value) \
-	((value) & ED_MPS_PACKET_SIZE_MASK)
-#define ED_MPS_TRANS_OPPORTUNITIES_GET(value) \
-	((((value) >> 10) & 0x3) + 1)
-
+#define USB_ED_GET_MPS(ed) \
+	(uint16_usb2host((ed).max_packet_size) & 0x7ff)
+#define USB_ED_GET_ADD_OPPS(ed) \
+	((uint16_usb2host((ed).max_packet_size) >> 11) & 0x3)
 	/** Polling interval in milliseconds.
 	 * Ignored for bulk and control endpoints.
@@ -246,8 +247,6 @@
 	 */
 	uint8_t attributes;
-#define SS_COMPANION_MAX_STREAMS(attributes) \
-	(attributes & 0x1f)
-#define SS_COMPANION_MULT(attributes) \
-	(attributes & 0x3)
+#define USB_SSC_MAX_STREAMS(sscd) ((sscd).attributes & 0x1f)
+#define USB_SSC_MULT(sscd) ((sscd).attributes & 0x3)
 	/** The total number of bytes this endpoint will transfer
 	 * every service interval (SI).
Index: uspace/lib/usbdev/include/usb/dev/pipes.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/pipes.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbdev/include/usb/dev/pipes.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -37,5 +37,5 @@
 #include <usb/usb.h>
 #include <usb/descriptor.h>
-#include <usb_iface.h>
+#include <usbhc_iface.h>
 
 #include <stdbool.h>
@@ -44,12 +44,14 @@
 
 #define CTRL_PIPE_MIN_PACKET_SIZE 8
+
 /** Abstraction of a logical connection to USB device endpoint.
- * It encapsulates endpoint attributes (transfer type etc.).
+ * It contains some vital information about the pipe.
  * This endpoint must be bound with existing usb_device_connection_t
  * (i.e. the wire to send data over).
  */
 typedef struct {
-	/** Endpoint description */
-	usb_endpoint_desc_t desc;
+	/** Pipe description received from HC */
+	usb_pipe_desc_t desc;
+
 	/** Whether to automatically reset halt on the endpoint.
 	 * Valid only for control endpoint zero.
@@ -100,5 +102,5 @@
 } usb_endpoint_mapping_t;
 
-int usb_pipe_initialize(usb_pipe_t *, usb_dev_session_t *, const usb_endpoint_desc_t *);
+int usb_pipe_initialize(usb_pipe_t *, usb_dev_session_t *, usb_transfer_type_t);
 int usb_pipe_initialize_default_control(usb_pipe_t *, usb_dev_session_t *);
 
@@ -106,5 +108,5 @@
     size_t, const uint8_t *, size_t, usb_dev_session_t *);
 
-int usb_pipe_register(usb_pipe_t *);
+int usb_pipe_register(usb_pipe_t *, const usb_standard_endpoint_descriptor_t *, const usb_superspeed_endpoint_companion_descriptor_t *);
 int usb_pipe_unregister(usb_pipe_t *);
 
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbdev/src/devdrv.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -255,11 +255,13 @@
 
 	/* Register created pipes. */
+	unsigned pipes_registered = 0;
 	for (size_t i = 0; i < pipe_count; i++) {
 		if (pipes[i].present) {
-			rc = usb_pipe_register(&pipes[i].pipe);
+			rc = usb_pipe_register(&pipes[i].pipe, pipes[i].descriptor, pipes[i].companion_descriptor);
 			if (rc != EOK) {
 				goto rollback_unregister_endpoints;
 			}
 		}
+		pipes_registered++;
 	}
 
@@ -276,5 +278,5 @@
 	 */
 rollback_unregister_endpoints:
-	for (size_t i = 0; i < pipe_count; i++) {
+	for (size_t i = 0; i < pipes_registered; i++) {
 		if (pipes[i].present) {
 			usb_pipe_unregister(&pipes[i].pipe);
@@ -419,6 +421,5 @@
 	/* This pipe was registered by the hub driver,
 	 * during device initialization. */
-	int rc = usb_pipe_initialize_default_control(
-	    &usb_dev->ctrl_pipe, usb_dev->bus_session);
+	int rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe, usb_dev->bus_session);
 	if (rc != EOK) {
 		usb_dev_disconnect(usb_dev->bus_session);
Index: uspace/lib/usbdev/src/devpoll.c
===================================================================
--- uspace/lib/usbdev/src/devpoll.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbdev/src/devpoll.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -96,5 +96,5 @@
 		    (int) mapping->interface->interface_subclass,
 		    (int) mapping->interface->interface_protocol,
-		    data->request_size, pipe->desc.max_packet_size);
+		    data->request_size, pipe->desc.max_transfer_size);
 	}
 
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbdev/src/pipes.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -272,40 +272,43 @@
  * @param pipe Endpoint pipe to be initialized.
  * @param bus_session Endpoint pipe to be initialized.
- * @param ep_desc Prepared endpoint descriptor
- * @return Error code.
- */
-int usb_pipe_initialize(usb_pipe_t *pipe,
-    usb_dev_session_t *bus_session,
-    const usb_endpoint_desc_t *ep_desc)
-{
-	int ret = EOK;
-	assert(pipe);
-
-	pipe->desc = *ep_desc;
+ * @return Error code.
+ */
+int usb_pipe_initialize(usb_pipe_t *pipe, usb_dev_session_t *bus_session, usb_transfer_type_t transfer_type)
+{
+	assert(pipe);
+
 	pipe->auto_reset_halt = false;
 	pipe->bus_session = bus_session;
 
-	if (pipe->desc.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
-		ret = usb_isoch_session_initialize(pipe);
-	}
-
-	return ret;
-}
-
-static const usb_endpoint_desc_t default_control_ep_desc = {
-	.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
+	if (transfer_type == USB_TRANSFER_ISOCHRONOUS)
+		return usb_isoch_session_initialize(pipe);
+
+	return EOK;
+}
+
+static const usb_pipe_desc_t default_control_pipe = {
+	.endpoint_no = 0,
+	.transfer_type = USB_TRANSFER_CONTROL,
 	.direction = USB_DIRECTION_BOTH,
-	.packets = 1,
+	.max_transfer_size = CTRL_PIPE_MIN_PACKET_SIZE,
 };
 
-/** Initialize USB endpoint pipe as the default zero control pipe.
+/** Initialize USB default control pipe.
+ *
+ * This one is special because it must not be registered, it is registered automatically.
  *
  * @param pipe Endpoint pipe to be initialized.
- * @param bus_session
+ * @param bus_session Endpoint pipe to be initialized.
  * @return Error code.
  */
 int usb_pipe_initialize_default_control(usb_pipe_t *pipe, usb_dev_session_t *bus_session)
 {
-	return usb_pipe_initialize(pipe, bus_session, &default_control_ep_desc); 
+	const int ret = usb_pipe_initialize(pipe, bus_session, USB_TRANSFER_CONTROL);
+	if (ret)
+		return ret;
+
+	pipe->desc = default_control_pipe;
+
+	return EOK;
 }
 
@@ -313,11 +316,13 @@
  *
  * @param pipe Pipe to be registered.
- * @param interval Polling interval.
- * @return Error code.
- */
-int usb_pipe_register(usb_pipe_t *pipe)
+ * @param ep_desc Matched endpoint descriptor
+ * @param comp_desc Matched superspeed companion descriptro, if any
+ * @return Error code.
+ */
+int usb_pipe_register(usb_pipe_t *pipe, const usb_standard_endpoint_descriptor_t *ep_desc, const usb_superspeed_endpoint_companion_descriptor_t *comp_desc)
 {
 	assert(pipe);
 	assert(pipe->bus_session);
+	assert(ep_desc);
 
 	async_exch_t *exch = async_exchange_begin(pipe->bus_session);
@@ -325,6 +330,22 @@
 		return ENOMEM;
 
-	const int ret = usbhc_register_endpoint(exch, &pipe->desc);
-
+	usb_endpoint_descriptors_t descriptors;
+
+#define COPY(field) descriptors.endpoint.field = ep_desc->field
+	COPY(endpoint_address);
+	COPY(attributes);
+	COPY(max_packet_size);
+	COPY(poll_interval);
+#undef COPY
+
+#define COPY(field) descriptors.companion.field = comp_desc->field
+	if (comp_desc) {
+		COPY(max_burst);
+		COPY(attributes);
+		COPY(bytes_per_interval);
+	}
+#undef COPY
+
+	const int ret = usbhc_register_endpoint(exch, &pipe->desc, &descriptors);
 	async_exchange_end(exch);
 	return ret;
Index: uspace/lib/usbdev/src/pipesinit.c
===================================================================
--- uspace/lib/usbdev/src/pipesinit.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbdev/src/pipesinit.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -156,39 +156,4 @@
 }
 
-static void parse_endpoint_descriptors(usb_endpoint_desc_t *ep_desc,
-    usb_standard_endpoint_descriptor_t *endpoint_desc,
-    usb_superspeed_endpoint_companion_descriptor_t *companion_desc)
-{
-	*ep_desc = (usb_endpoint_desc_t) {
-		/* Actual endpoint number is in bits 0..3 */
-		.endpoint_no = endpoint_desc->endpoint_address & 0x0F,
-		/* Transfer type is in bits 0..2 and
-		 * the enum values corresponds 1:1 */
-		.transfer_type = endpoint_desc->attributes & 3,
-		/* Endpoint direction is set by bit 7 */
-		.direction = (endpoint_desc->endpoint_address & 128)
-		    ? USB_DIRECTION_IN : USB_DIRECTION_OUT,
-		// FIXME: USB2 max_packet_size is limited to 1023 bytes, 1024+ doesn't work for USB3
-		// See 4.14.2.1.1 of XHCI specification -> possibly refactor into one somehow-named field
-		.max_packet_size
-			= ED_MPS_PACKET_SIZE_GET(uint16_usb2host(endpoint_desc->max_packet_size)),
-		.interval = endpoint_desc->poll_interval,
-		// FIXME: USB2 packets and USB3 max_burst are probably the same thing
-		.packets = ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(endpoint_desc->max_packet_size)),
-	};
-
-	if (companion_desc) {
-		ep_desc->usb3 = (usb3_endpoint_desc_t) {
-			.max_burst = companion_desc->max_burst,
-			.max_streams
-				= SS_COMPANION_MAX_STREAMS(companion_desc->attributes),
-			.bytes_per_interval
-				= companion_desc->bytes_per_interval,
-			.mult = SS_COMPANION_MULT(companion_desc->attributes),
-		};
-	}
-}
-
-
 /** Process endpoint descriptor.
  *
@@ -211,10 +176,7 @@
 	 * Get endpoint characteristics.
 	 */
-	usb_endpoint_desc_t ep_desc;
-	parse_endpoint_descriptors(&ep_desc, endpoint_desc, companion_desc);
-
 	const usb_endpoint_description_t description = {
-		.direction = ep_desc.direction,
-		.transfer_type = ep_desc.transfer_type,
+		.transfer_type = USB_ED_GET_TRANSFER_TYPE(*endpoint_desc),
+		.direction = USB_ED_GET_DIR(*endpoint_desc),
 
 		/* Get interface characteristics. */
@@ -238,5 +200,5 @@
 	}
 
-	int err = usb_pipe_initialize(&ep_mapping->pipe, bus_session, &ep_desc);
+	int err = usb_pipe_initialize(&ep_mapping->pipe, bus_session, description.transfer_type);
 	if (err)
 		return err;
Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -109,5 +109,5 @@
 	int (*device_offline)(device_t *);			/**< Optional */
 	endpoint_t *(*device_find_endpoint)(device_t*, usb_target_t, usb_direction_t);
-	endpoint_t *(*endpoint_create)(device_t *, const usb_endpoint_desc_t *);
+	endpoint_t *(*endpoint_create)(device_t *, const usb_endpoint_descriptors_t *);
 
 	/* Operations on endpoint */
@@ -163,5 +163,5 @@
     const char *);
 
-int bus_endpoint_add(device_t *, const usb_endpoint_desc_t *, endpoint_t **);
+int bus_endpoint_add(device_t *, const usb_endpoint_descriptors_t *, endpoint_t **);
 endpoint_t *bus_find_endpoint(device_t *, usb_target_t, usb_direction_t);
 int bus_endpoint_remove(endpoint_t *);
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -46,4 +46,5 @@
 #include <usb/usb.h>
 #include <usb/host/bus.h>
+#include <usbhc_iface.h>
 
 typedef struct bus bus_t;
@@ -59,14 +60,4 @@
 	/** Reference count. */
 	atomic_t refcnt;
-	/** Enpoint number */
-	usb_endpoint_t endpoint;
-	/** Communication direction. */
-	usb_direction_t direction;
-	/** USB transfer type. */
-	usb_transfer_type_t transfer_type;
-	/** Maximum size of data packets. */
-	size_t max_packet_size;
-	/** Additional opportunities per uframe */
-	unsigned packets;
 	/** Reserved bandwidth. */
 	size_t bandwidth;
@@ -80,8 +71,22 @@
 	fibril_condvar_t avail;
 
+	/** Enpoint number */
+	usb_endpoint_t endpoint;
+	/** Communication direction. */
+	usb_direction_t direction;
+	/** USB transfer type. */
+	usb_transfer_type_t transfer_type;
+	/** Maximum size of one packet */
+	size_t max_packet_size;
+
+	/** Maximum size of one transfer */
+	size_t max_transfer_size;
+	/** Number of packats that can be sent in one service interval (not necessarily uframe) */
+	unsigned packets_per_uframe;
+
 	/* This structure is meant to be extended by overriding. */
 } endpoint_t;
 
-extern void endpoint_init(endpoint_t *, device_t *, const usb_endpoint_desc_t *);
+extern void endpoint_init(endpoint_t *, device_t *, const usb_endpoint_descriptors_t *);
 
 extern void endpoint_add_ref(endpoint_t *);
Index: uspace/lib/usbhost/src/bus.c
===================================================================
--- uspace/lib/usbhost/src/bus.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbhost/src/bus.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -128,5 +128,5 @@
 }
 
-int bus_endpoint_add(device_t *device, const usb_endpoint_desc_t *desc, endpoint_t **out_ep)
+int bus_endpoint_add(device_t *device, const usb_endpoint_descriptors_t *desc, endpoint_t **out_ep)
 {
 	int err;
@@ -134,9 +134,4 @@
 
 	bus_t *bus = device->bus;
-
-	if (desc->max_packet_size == 0 || desc->packets == 0) {
-		usb_log_warning("Invalid endpoint description (mps %zu, %u packets)", desc->max_packet_size, desc->packets);
-		return EINVAL;
-	}
 
 	const bus_ops_t *create_ops = BUS_OPS_LOOKUP(bus->ops, endpoint_create);
@@ -149,6 +144,20 @@
 		return ENOMEM;
 
-	/* Temporary reference */
+	/* Bus reference */
 	endpoint_add_ref(ep);
+
+	if (ep->max_transfer_size == 0) {
+		usb_log_warning("Invalid endpoint description (mps %zu, "
+			"%u packets)", ep->max_packet_size, ep->packets_per_uframe);
+		/* Bus reference */
+		endpoint_del_ref(ep);
+		return EINVAL;
+	}
+
+	usb_log_debug("Register endpoint %d:%d %s-%s %zuB.\n",
+	    device->address, ep->endpoint,
+	    usb_str_transfer_type(ep->transfer_type),
+	    usb_str_direction(ep->direction),
+	    ep->max_transfer_size);
 
 	fibril_mutex_lock(&bus->guard);
@@ -162,6 +171,4 @@
 	}
 
-	/* Temporary reference */
-	endpoint_del_ref(ep);
 	return err;
 }
@@ -193,10 +200,19 @@
 {
 	assert(ep);
+	assert(ep->device);
+	assert(ep->device->bus);
+	assert(ep->device->bus->ops);
 
 	bus_t *bus = endpoint_get_bus(ep);
 
-	const bus_ops_t *ops = BUS_OPS_LOOKUP(ep->device->bus->ops, endpoint_unregister);
-	if (!ops)
-		return ENOTSUP;
+	const bus_ops_t *ops = BUS_OPS_LOOKUP(bus->ops, endpoint_unregister);
+	if (!ops)
+		return ENOTSUP;
+
+	usb_log_debug("Unregister endpoint %d:%d %s-%s %zuB.\n",
+	    ep->device->address, ep->endpoint,
+	    usb_str_transfer_type(ep->transfer_type),
+	    usb_str_direction(ep->direction),
+	    ep->max_transfer_size);
 
 	fibril_mutex_lock(&bus->guard);
Index: uspace/lib/usbhost/src/ddf_helpers.c
===================================================================
--- uspace/lib/usbhost/src/ddf_helpers.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbhost/src/ddf_helpers.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -50,4 +50,5 @@
 
 #include "bus.h"
+#include "endpoint.h"
 
 #include "ddf_helpers.h"
@@ -65,6 +66,6 @@
  * @return Error code.
  */
-static int register_endpoint(
-	ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
+static int register_endpoint(ddf_fun_t *fun, usb_pipe_desc_t *pipe_desc,
+     const usb_endpoint_descriptors_t *ep_desc)
 {
 	assert(fun);
@@ -75,11 +76,18 @@
 	assert(dev);
 
-	usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
-		dev->address, endpoint_desc->endpoint_no,
-		usb_str_transfer_type(endpoint_desc->transfer_type),
-		usb_str_direction(endpoint_desc->direction),
-		endpoint_desc->max_packet_size, endpoint_desc->interval);
-
-	return bus_endpoint_add(dev, endpoint_desc, NULL);
+	endpoint_t *ep;
+	const int err = bus_endpoint_add(dev, ep_desc, &ep);
+	if (err)
+		return err;
+
+	if (pipe_desc) {
+		pipe_desc->endpoint_no = ep->endpoint;
+		pipe_desc->direction = ep->direction;
+		pipe_desc->transfer_type = ep->transfer_type;
+		pipe_desc->max_transfer_size = ep->max_transfer_size;
+	}
+	endpoint_del_ref(ep);
+
+	return EOK;
 }
 
@@ -89,6 +97,5 @@
   * @return Error code.
   */
-static int unregister_endpoint(
-	ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)
+static int unregister_endpoint(ddf_fun_t *fun, const usb_pipe_desc_t *endpoint_desc)
 {
 	assert(fun);
@@ -103,8 +110,4 @@
 		.endpoint = endpoint_desc->endpoint_no
 	}};
-
-	usb_log_debug("Unregister endpoint %d:%d %s.\n",
-		dev->address, endpoint_desc->endpoint_no,
-		usb_str_direction(endpoint_desc->direction));
 
 	endpoint_t *ep = bus_find_endpoint(dev, target, endpoint_desc->direction);
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbhost/src/endpoint.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -41,4 +41,5 @@
 #include <str_error.h>
 #include <usb/debug.h>
+#include <usb/descriptor.h>
 #include <usb/host/hcd.h>
 
@@ -50,5 +51,5 @@
 /** Initialize provided endpoint structure.
  */
-void endpoint_init(endpoint_t *ep, device_t *dev, const usb_endpoint_desc_t *desc)
+void endpoint_init(endpoint_t *ep, device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
 	memset(ep, 0, sizeof(endpoint_t));
@@ -62,11 +63,17 @@
 	fibril_condvar_initialize(&ep->avail);
 
-	ep->endpoint = desc->endpoint_no;
-	ep->direction = desc->direction;
-	ep->transfer_type = desc->transfer_type;
-	ep->max_packet_size = desc->max_packet_size;
-	ep->packets = desc->packets;
-
-	ep->bandwidth = endpoint_count_bw(ep, desc->max_packet_size);
+	ep->endpoint = USB_ED_GET_EP(desc->endpoint);
+	ep->direction = USB_ED_GET_DIR(desc->endpoint);
+	ep->transfer_type = USB_ED_GET_TRANSFER_TYPE(desc->endpoint);
+	ep->max_packet_size = USB_ED_GET_MPS(desc->endpoint);
+	ep->packets_per_uframe = USB_ED_GET_ADD_OPPS(desc->endpoint) + 1;
+
+	/** Direction both is our construct never present in descriptors */
+	if (ep->transfer_type == USB_TRANSFER_CONTROL)
+		ep->direction = USB_DIRECTION_BOTH;
+
+	ep->max_transfer_size = ep->max_packet_size * ep->packets_per_uframe;
+
+	ep->bandwidth = endpoint_count_bw(ep, ep->max_transfer_size);
 }
 
Index: uspace/lib/usbhost/src/usb2_bus.c
===================================================================
--- uspace/lib/usbhost/src/usb2_bus.c	(revision c90163262531a9d6fd0787466623f8e3732fd826)
+++ uspace/lib/usbhost/src/usb2_bus.c	(revision 9efad54470c08d7d51f40a9febdaa103916aec6f)
@@ -186,13 +186,4 @@
 }
 
-static const usb_endpoint_desc_t usb2_default_control_ep = {
-	.endpoint_no = 0,
-	.transfer_type = USB_TRANSFER_CONTROL,
-	.direction = USB_DIRECTION_BOTH,
-	.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
-	.packets = 1,
-};
-
-
 static const usb_target_t usb2_default_target = {{
 	.address = USB_ADDRESS_DEFAULT,
@@ -221,6 +212,9 @@
 	usb_log_debug("Device(%d): Adding default target (0:0)", address);
 
+	usb_endpoint_descriptors_t ep0_desc = {
+	    .endpoint.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
+	};
 	endpoint_t *default_ep;
-	err = bus_endpoint_add(dev, &usb2_default_control_ep, &default_ep);
+	err = bus_endpoint_add(dev, &ep0_desc, &default_ep);
 	if (err != EOK) {
 		usb_log_error("Device(%d): Failed to add default target: %s.",
@@ -229,6 +223,5 @@
 	}
 
-	uint16_t max_packet_size;
-	if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, &bus->base, dev)))
+	if ((err = hcd_get_ep0_max_packet_size(&ep0_desc.endpoint.max_packet_size, &bus->base, dev)))
 		goto err_address;
 
@@ -254,15 +247,7 @@
 	dev->address = address;
 
-	const usb_endpoint_desc_t control_ep = {
-		.endpoint_no = 0,
-		.transfer_type = USB_TRANSFER_CONTROL,
-		.direction = USB_DIRECTION_BOTH,
-		.max_packet_size = max_packet_size,
-		.packets = 1,
-	};
-
 	/* Register EP on the new address */
 	usb_log_debug("Device(%d): Registering control EP.", address);
-	err = bus_endpoint_add(dev, &control_ep, NULL);
+	err = bus_endpoint_add(dev, &ep0_desc, NULL);
 	if (err != EOK) {
 		usb_log_error("Device(%d): Failed to register EP0: %s",
@@ -352,5 +337,5 @@
 }
 
-static endpoint_t *usb2_bus_create_ep(device_t *dev, const usb_endpoint_desc_t *desc)
+static endpoint_t *usb2_bus_create_ep(device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
 	endpoint_t *ep = malloc(sizeof(endpoint_t));
