Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision e7e1fd38e5e2b8703e15c6b4f74c5357ba1c2038)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision a6afb4c8b46f2fd061c625a25b38c08e55f59201)
@@ -60,10 +60,15 @@
  * Negative values could be used to indicate error.
  */
-typedef int16_t usb_endpoint_t;
+typedef uint16_t usb_endpoint_t;
 
 /** USB address type.
  * Negative values could be used to indicate error.
  */
-typedef int16_t usb_address_t;
+typedef uint16_t usb_address_t;
+
+/**
+ * USB Stream ID type.
+ */
+typedef uint16_t usb_stream_t;
 
 /** USB transfer type. */
@@ -72,6 +77,8 @@
 	USB_TRANSFER_ISOCHRONOUS = 1,
 	USB_TRANSFER_BULK = 2,
-	USB_TRANSFER_INTERRUPT = 3
+	USB_TRANSFER_INTERRUPT = 3,
 } usb_transfer_type_t;
+
+#define USB_TRANSFER_COUNT  (USB_TRANSFER_INTERRUPT + 1)
 
 /** USB data transfer direction. */
@@ -79,6 +86,8 @@
 	USB_DIRECTION_IN,
 	USB_DIRECTION_OUT,
-	USB_DIRECTION_BOTH
+	USB_DIRECTION_BOTH,
 } usb_direction_t;
+
+#define USB_DIRECTION_COUNT  (USB_DIRECTION_BOTH + 1)
 
 /** USB complete address type.
@@ -89,5 +98,5 @@
 		usb_address_t address;
 		usb_endpoint_t endpoint;
-		uint32_t stream;
+		usb_stream_t stream;
 	} __attribute__((packed));
 	uint64_t packed;
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision e7e1fd38e5e2b8703e15c6b4f74c5357ba1c2038)
+++ uspace/lib/usb/include/usb/usb.h	(revision a6afb4c8b46f2fd061c625a25b38c08e55f59201)
@@ -63,4 +63,9 @@
 }
 
+static inline bool usb_speed_is_valid(const usb_speed_t s)
+{
+	return (s >= USB_SPEED_LOW) && (s < USB_SPEED_MAX);
+}
+
 const char *usb_str_speed(usb_speed_t);
 
@@ -97,5 +102,5 @@
 static inline bool usb_address_is_valid(usb_address_t a)
 {
-	return (a >= USB_ADDRESS_DEFAULT) && (a <= USB11_ADDRESS_MAX);
+	return a <= USB11_ADDRESS_MAX;
 }
 
@@ -105,4 +110,7 @@
 /** Maximum endpoint number in USB */
 #define USB_ENDPOINT_MAX 16
+
+/** There might be two directions for every endpoint number (except 0) */
+#define USB_ENDPOINT_COUNT (2 * USB_ENDPOINT_MAX)
 
 /** Check USB endpoint for allowed values.
@@ -115,17 +123,19 @@
 static inline bool usb_endpoint_is_valid(usb_endpoint_t ep)
 {
-	return (ep >= USB_ENDPOINT_DEFAULT_CONTROL) &&
-	    (ep < USB_ENDPOINT_MAX);
+	return ep < USB_ENDPOINT_MAX;
 }
 
-/** Check USB target for allowed values (address and endpoint).
+/**
+ * Check USB target for allowed values (address, endpoint, stream).
  *
  * @param target.
  * @return True, if values are wihtin limits, false otherwise.
  */
-static inline bool usb_target_is_valid(usb_target_t target)
+static inline bool usb_target_is_valid(usb_target_t *target)
 {
-	return usb_address_is_valid(target.address) &&
-	    usb_endpoint_is_valid(target.endpoint);
+	return usb_address_is_valid(target->address) &&
+	    usb_endpoint_is_valid(target->endpoint);
+
+	// A 16-bit Stream ID is always valid.
 }
 
@@ -136,5 +146,5 @@
  * @return Whether @p a and @p b points to the same pipe on the same device.
  */
-static inline int usb_target_same(usb_target_t a, usb_target_t b)
+static inline bool usb_target_same(usb_target_t a, usb_target_t b)
 {
 	return (a.address == b.address)
@@ -142,8 +152,13 @@
 }
 
-/** General handle type.
- * Used by various USB functions as opaque handle.
- */
-typedef sysarg_t usb_handle_t;
+static inline bool usb_transfer_type_is_valid(usb_transfer_type_t type)
+{
+	return (type >= 0) && (type < USB_TRANSFER_COUNT);
+}
+
+static inline bool usb_direction_is_valid(usb_direction_t dir)
+{
+	return (dir >= 0) && (dir < USB_DIRECTION_COUNT);
+}
 
 /** USB packet identifier. */
Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision e7e1fd38e5e2b8703e15c6b4f74c5357ba1c2038)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision a6afb4c8b46f2fd061c625a25b38c08e55f59201)
@@ -84,5 +84,5 @@
 	usb_speed_t speed;
 	usb_address_t address;
-	endpoint_t *endpoints [2 * USB_ENDPOINT_MAX];
+	endpoint_t *endpoints [USB_ENDPOINT_COUNT];
 
 	/* Managing bus */
Index: uspace/lib/usbhost/src/bus.c
===================================================================
--- uspace/lib/usbhost/src/bus.c	(revision e7e1fd38e5e2b8703e15c6b4f74c5357ba1c2038)
+++ uspace/lib/usbhost/src/bus.c	(revision a6afb4c8b46f2fd061c625a25b38c08e55f59201)
@@ -42,4 +42,5 @@
 #include <errno.h>
 #include <mem.h>
+#include <macros.h>
 #include <stdio.h>
 #include <str_error.h>
@@ -345,5 +346,5 @@
  * For different arguments, the result is stable but not defined.
  */
-static int bus_endpoint_index(usb_endpoint_t ep, usb_direction_t dir)
+static size_t bus_endpoint_index(usb_endpoint_t ep, usb_direction_t dir)
 {
 	return 2 * ep + (dir == USB_DIRECTION_OUT);
@@ -384,10 +385,15 @@
 	endpoint_add_ref(ep);
 
+	const size_t idx = bus_endpoint_index(ep->endpoint, ep->direction);
+	if (idx >= ARRAY_SIZE(device->endpoints)) {
+		usb_log_warning("Invalid endpoint description (ep no %u out of "
+		    "bounds)", ep->endpoint);
+		goto drop;
+	}
+
 	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;
+		goto drop;
 	}
 
@@ -397,6 +403,4 @@
 	    usb_str_direction(ep->direction),
 	    ep->max_transfer_size);
-
-	const int idx = bus_endpoint_index(ep->endpoint, ep->direction);
 
 	fibril_mutex_lock(&device->guard);
@@ -423,4 +427,8 @@
 
 	return EOK;
+drop:
+	/* Bus reference */
+	endpoint_del_ref(ep);
+	return EINVAL;
 }
 
@@ -428,18 +436,22 @@
  * Search for an endpoint. Returns a reference.
  */
-endpoint_t *bus_find_endpoint(device_t *device, usb_endpoint_t endpoint, usb_direction_t dir)
+endpoint_t *bus_find_endpoint(device_t *device, usb_endpoint_t endpoint,
+    usb_direction_t dir)
 {
 	assert(device);
 
-	const int idx = bus_endpoint_index(endpoint, dir);
-	const int ctrl_idx = bus_endpoint_index(endpoint, USB_DIRECTION_BOTH);
+	const size_t idx = bus_endpoint_index(endpoint, dir);
+	const size_t ctrl_idx = bus_endpoint_index(endpoint, USB_DIRECTION_BOTH);
+
+	endpoint_t *ep = NULL;
 
 	fibril_mutex_lock(&device->guard);
-	endpoint_t *ep = device->endpoints[idx];
+	if (idx < ARRAY_SIZE(device->endpoints))
+		ep = device->endpoints[idx];
 	/*
 	 * If the endpoint was not found, it's still possible it is a control
 	 * endpoint having direction BOTH.
 	 */
-	if (!ep) {
+	if (!ep && ctrl_idx < ARRAY_SIZE(device->endpoints)) {
 		ep = device->endpoints[ctrl_idx];
 		if (ep && ep->transfer_type != USB_TRANSFER_CONTROL)
@@ -478,5 +490,8 @@
 	    ep->max_transfer_size);
 
-	const int idx = bus_endpoint_index(ep->endpoint, ep->direction);
+	const size_t idx = bus_endpoint_index(ep->endpoint, ep->direction);
+
+	if (idx >= ARRAY_SIZE(device->endpoints))
+		return EINVAL;
 
 	fibril_mutex_lock(&device->guard);
@@ -495,8 +510,5 @@
 
 /**
- * Reserve the default address on the bus. Also, report the speed of the device
- * that is listening on the default address.
- *
- * The speed is then used for devices enumerated while the address is reserved.
+ * Reserve the default address on the bus for the specified device (hub).
  */
 int bus_reserve_default_address(bus_t *bus, device_t *dev)
@@ -564,6 +576,18 @@
 	assert(ep->device == device);
 
-	const int err = endpoint_send_batch(ep, target, direction, data, size, setup_data,
-	    on_complete, arg, name);
+	/*
+	 * This method is already callable from HC only, so we can force these
+	 * conditions harder.
+	 * Invalid values from devices shall be caught on DDF interface already.
+	 */
+	assert(usb_target_is_valid(&target));
+	assert(usb_direction_is_valid(direction));
+	assert(direction != USB_DIRECTION_BOTH);
+	assert(size == 0 || data != NULL);
+	assert(arg == NULL || on_complete != NULL);
+	assert(name);
+
+	const int err = endpoint_send_batch(ep, target, direction,
+	    data, size, setup_data, on_complete, arg, name);
 
 	/* Temporary reference */
@@ -573,8 +597,11 @@
 }
 
+/**
+ * A structure to pass data from the completion callback to the caller.
+ */
 typedef struct {
 	fibril_mutex_t done_mtx;
 	fibril_condvar_t done_cv;
-	unsigned done;
+	bool done;
 
 	size_t transferred_size;
@@ -592,5 +619,5 @@
 	d->error = error;
 	fibril_mutex_lock(&d->done_mtx);
-	d->done = 1;
+	d->done = true;
 	fibril_condvar_broadcast(&d->done_cv);
 	fibril_mutex_unlock(&d->done_mtx);
@@ -599,5 +626,5 @@
 
 /**
- * Issue a transfer on the bus, wait for result.
+ * Issue a transfer on the bus, wait for the result.
  *
  * @param device Device for which to send the batch
@@ -613,18 +640,20 @@
     const char *name)
 {
-	sync_data_t sd = { .done = 0 };
+	sync_data_t sd = { .done = false };
 	fibril_mutex_initialize(&sd.done_mtx);
 	fibril_condvar_initialize(&sd.done_cv);
 
 	const int ret = bus_device_send_batch(device, target, direction,
-	    data, size, setup_data,
-	    sync_transfer_complete, &sd, name);
+	    data, size, setup_data, sync_transfer_complete, &sd, name);
 	if (ret != EOK)
 		return ret;
 
+	/*
+	 * Note: There are requests that are completed synchronously. It is not
+	 *       therefore possible to just lock the mutex before and wait.
+	 */
 	fibril_mutex_lock(&sd.done_mtx);
-	while (!sd.done) {
+	while (!sd.done)
 		fibril_condvar_wait(&sd.done_cv, &sd.done_mtx);
-	}
 	fibril_mutex_unlock(&sd.done_mtx);
 
Index: uspace/lib/usbhost/src/ddf_helpers.c
===================================================================
--- uspace/lib/usbhost/src/ddf_helpers.c	(revision e7e1fd38e5e2b8703e15c6b4f74c5357ba1c2038)
+++ uspace/lib/usbhost/src/ddf_helpers.c	(revision a6afb4c8b46f2fd061c625a25b38c08e55f59201)
@@ -154,4 +154,7 @@
 	int err;
 
+	if (!usb_speed_is_valid(speed))
+		return EINVAL;
+
 	usb_log_debug("Hub %d reported a new %s speed device on port: %u",
 	    hub->address, usb_str_speed(speed), port);
@@ -212,5 +215,5 @@
 
 	if (!victim) {
-		usb_log_warning("Hub '%s' tried to remove non-existant"
+		usb_log_warning("Hub '%s' tried to remove non-existent"
 		    " device.", ddf_fun_get_name(fun));
 		return ENOENT;
@@ -271,4 +274,13 @@
 	target.address = dev->address;
 
+	if (!usb_target_is_valid(&target))
+		return EINVAL;
+
+	if (size > 0 && data == NULL)
+		return EBADMEM;
+
+	if (!callback && arg)
+		return EBADMEM;
+
 	return bus_device_send_batch(dev, target, USB_DIRECTION_IN,
 	    data, size, setup_data,
@@ -295,4 +307,13 @@
 
 	target.address = dev->address;
+
+	if (!usb_target_is_valid(&target))
+		return EINVAL;
+
+	if (size > 0 && data == NULL)
+		return EBADMEM;
+
+	if (!callback && arg)
+		return EBADMEM;
 
 	return bus_device_send_batch(dev, target, USB_DIRECTION_OUT,
