diff --git a/Cargo.toml b/Cargo.toml
index 3155106e9d79fc478ea7c9669c79fefd6124b884..1d1ad6e18f6a1651f9c5a59a5d4d4f70640e6c5c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,12 +18,13 @@ arrayref = "0.3.6"
 subtle = { version = "2.2", default-features = false, features = ["nightly"] }
 
 [features]
-std = ["cbor/std", "crypto/std", "crypto/derive_debug"]
+debug_allocations = ["libtock/debug_allocations"]
 debug_ctap = ["crypto/derive_debug"]
-with_ctap1 = ["crypto/with_ctap1"]
 panic_console = ["libtock/panic_console"]
-debug_allocations = ["libtock/debug_allocations"]
+std = ["cbor/std", "crypto/std", "crypto/derive_debug"]
 ram_storage = []
+verbose = ["debug_ctap"]
+with_ctap1 = ["crypto/with_ctap1"]
 
 [dev-dependencies]
 elf2tab = "0.4.0"
diff --git a/deploy.py b/deploy.py
index 8b5ec81a1cf10b8401fb1b384f1cf05977b4a1ea..814cb9f6254ad7962b380c75ee3e103b442acd8f 100755
--- a/deploy.py
+++ b/deploy.py
@@ -701,6 +701,15 @@ if __name__ == "__main__":
             "output messages before starting blinking the LEDs on the "
             "board."),
   )
+  main_parser.add_argument(
+      "--debug",
+      action="append_const",
+      const="debug_ctap",
+      dest="features",
+      help=("Compiles and installs the OpenSK application in debug mode "
+            "(i.e. more debug messages will be sent over the console port "
+            "such as hexdumps of packets)."),
+  )
   main_parser.add_argument(
       "--debug-allocations",
       action="append_const",
@@ -709,6 +718,14 @@ if __name__ == "__main__":
       help=("The console will be used to output allocator statistics every "
             "time an allocation/deallocation happens."),
   )
+  main_parser.add_argument(
+      "--verbose",
+      action="append_const",
+      const="verbose",
+      dest="features",
+      help=("The console will be used to output verbose information about the "
+            "OpenSK application. This also automatically activates --debug."),
+  )
   main_parser.add_argument(
       "--no-u2f",
       action=RemoveConstAction,
@@ -727,15 +744,6 @@ if __name__ == "__main__":
             "This is useful to allow flashing multiple OpenSK authenticators "
             "in a row without them being considered clones."),
   )
-  main_parser.add_argument(
-      "--debug",
-      action="append_const",
-      const="debug_ctap",
-      dest="features",
-      help=("Compiles and installs the  OpenSK application in debug mode "
-            "(i.e. more debug messages will be sent over the console port "
-            "such as hexdumps of packets)."),
-  )
   main_parser.add_argument(
       "--no-persistent-storage",
       action="append_const",
diff --git a/run_desktop_tests.sh b/run_desktop_tests.sh
index 864b8fecca526ddc56726348472de28b8876a347..e38735315eb892bf2b5e74b225afffa3400b055d 100755
--- a/run_desktop_tests.sh
+++ b/run_desktop_tests.sh
@@ -34,8 +34,9 @@ cargo check --release --target=thumbv7em-none-eabi --features debug_ctap
 cargo check --release --target=thumbv7em-none-eabi --features panic_console
 cargo check --release --target=thumbv7em-none-eabi --features debug_allocations
 cargo check --release --target=thumbv7em-none-eabi --features ram_storage
+cargo check --release --target=thumbv7em-none-eabi --features verbose
 cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ctap1
-cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ctap1,panic_console,debug_allocations
+cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ctap1,panic_console,debug_allocations,verbose
 
 echo "Checking that examples build properly..."
 cargo check --release --target=thumbv7em-none-eabi --examples
diff --git a/src/usb_ctap_hid.rs b/src/usb_ctap_hid.rs
index 421e70b08e13a5a7d8e61dbf4dbac535fbec6e25..7e63754e24df7be59b20a2c73f0ad623186f25d6 100644
--- a/src/usb_ctap_hid.rs
+++ b/src/usb_ctap_hid.rs
@@ -165,6 +165,57 @@ pub fn send_or_recv(buf: &mut [u8; 64]) -> SendOrRecvStatus {
 pub fn recv_with_timeout(
     buf: &mut [u8; 64],
     timeout_delay: Duration<isize>,
+) -> Option<SendOrRecvStatus> {
+    #[cfg(feature = "verbose")]
+    writeln!(
+        Console::new(),
+        "Receiving packet with timeout of {}ms",
+        timeout_delay.ms(),
+    )
+    .unwrap();
+
+    let result = recv_with_timeout_detail(buf, timeout_delay);
+
+    #[cfg(feature = "verbose")]
+    {
+        if let Some(SendOrRecvStatus::Received) = result {
+            writeln!(Console::new(), "Received packet = {:02x?}", buf as &[u8]).unwrap();
+        }
+    }
+
+    result
+}
+
+// Same as send_or_recv, but with a timeout.
+// If the timeout elapses, return None.
+pub fn send_or_recv_with_timeout(
+    buf: &mut [u8; 64],
+    timeout_delay: Duration<isize>,
+) -> Option<SendOrRecvStatus> {
+    #[cfg(feature = "verbose")]
+    writeln!(
+        Console::new(),
+        "Sending packet with timeout of {}ms = {:02x?}",
+        timeout_delay.ms(),
+        buf as &[u8]
+    )
+    .unwrap();
+
+    let result = send_or_recv_with_timeout_detail(buf, timeout_delay);
+
+    #[cfg(feature = "verbose")]
+    {
+        if let Some(SendOrRecvStatus::Received) = result {
+            writeln!(Console::new(), "Received packet = {:02x?}", buf as &[u8]).unwrap();
+        }
+    }
+
+    result
+}
+
+fn recv_with_timeout_detail(
+    buf: &mut [u8; 64],
+    timeout_delay: Duration<isize>,
 ) -> Option<SendOrRecvStatus> {
     let result = syscalls::allow(DRIVER_NUMBER, allow_nr::RECEIVE, buf);
     if result.is_err() {
@@ -225,7 +276,7 @@ pub fn recv_with_timeout(
 
     // Cancel USB transaction if necessary.
     if status.get().is_none() {
-        #[cfg(feature = "debug_ctap")]
+        #[cfg(feature = "verbose")]
         writeln!(Console::new(), "Cancelling USB receive due to timeout").unwrap();
         let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::CANCEL, 0, 0) };
         match result_code {
@@ -249,9 +300,7 @@ pub fn recv_with_timeout(
     status.get()
 }
 
-// Same as send_or_recv, but with a timeout.
-// If the timeout elapses, return None.
-pub fn send_or_recv_with_timeout(
+fn send_or_recv_with_timeout_detail(
     buf: &mut [u8; 64],
     timeout_delay: Duration<isize>,
 ) -> Option<SendOrRecvStatus> {
@@ -317,7 +366,7 @@ pub fn send_or_recv_with_timeout(
 
     // Cancel USB transaction if necessary.
     if status.get().is_none() {
-        #[cfg(feature = "debug_ctap")]
+        #[cfg(feature = "verbose")]
         writeln!(Console::new(), "Cancelling USB transaction due to timeout").unwrap();
         let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::CANCEL, 0, 0) };
         match result_code {