Index: uspace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision 3faf416ce37ffbf7df67fe86c4f559fa80980afb)
+++ uspace/drv/usbmouse/main.c	(revision 019cff67b1d273e07778305dba7f81db87c94c27)
@@ -74,5 +74,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEBUG2, NAME);
 
 	return ddf_driver_main(&mouse_driver);
Index: uspace/drv/usbmouse/mouse.c
===================================================================
--- uspace/drv/usbmouse/mouse.c	(revision 3faf416ce37ffbf7df67fe86c4f559fa80980afb)
+++ uspace/drv/usbmouse/mouse.c	(revision 019cff67b1d273e07778305dba7f81db87c94c27)
@@ -94,4 +94,7 @@
 		}
 
+		usb_log_debug2("got buffer: %s.\n",
+		    usb_debug_str_buffer(buffer, buffer_size, 0));
+
 		uint8_t butt = buffer[0];
 		char str_buttons[4] = {
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 3faf416ce37ffbf7df67fe86c4f559fa80980afb)
+++ uspace/lib/usb/include/usb/debug.h	(revision 019cff67b1d273e07778305dba7f81db87c94c27)
@@ -79,4 +79,5 @@
 	usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
 
+const char *usb_debug_str_buffer(uint8_t *, size_t, size_t);
 
 
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 3faf416ce37ffbf7df67fe86c4f559fa80980afb)
+++ uspace/lib/usb/src/debug.c	(revision 019cff67b1d273e07778305dba7f81db87c94c27)
@@ -252,4 +252,64 @@
 }
 
+
+#define BUFFER_DUMP_LEN 512
+static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
+
+/** Dump buffer into string.
+ *
+ * The function dumps given buffer into hexadecimal format and stores it
+ * in a static fibril local string.
+ * That means that you do not have to deallocate the string (actually, you
+ * can not do that) and you do not have to save it agains concurrent
+ * calls to it.
+ * The only limitation is that each call rewrites the buffer again.
+ * Thus, it is necessary to copy the buffer elsewhere (that includes printing
+ * to screen or writing to file).
+ * Since this function is expected to be used for debugging prints only,
+ * that is not a big limitation.
+ *
+ * @warning You cannot use this function twice in the same printf
+ * (see detailed explanation).
+ *
+ * @param buffer Buffer to be printed (can be NULL).
+ * @param size Size of the buffer in bytes (can be zero).
+ * @param dumped_size How many bytes to actually dump (zero means all).
+ * @return Dumped buffer as a static (but fibril local) string.
+ */
+const char *usb_debug_str_buffer(uint8_t *buffer, size_t size,
+    size_t dumped_size)
+{
+	if (buffer == NULL) {
+		return "(null)";
+	}
+	if (size == 0) {
+		return "(empty)";
+	}
+	if ((dumped_size == 0) || (dumped_size > size)) {
+		dumped_size = size;
+	}
+
+	char *it = buffer_dump;
+
+	size_t index = 0;
+
+	while (1) {
+		/* FIXME: add range checking of the buffer size. */
+		snprintf(it, 4, "%02X ", (int) buffer[index]);
+		it += 3;
+		index++;
+		if (index >= dumped_size) {
+			break;
+		}
+	}
+
+	/* Remove the last space */
+	it--;
+	*it = 0;
+
+	return buffer_dump;
+}
+
+
 /**
  * @}
