WAIT! Before proceeding—if you don't know how to set up CircuitPython, check out: What is RPI PICO W and how to SETUP it?
Index
- Why Rubber Ducky, PICO Ducky, etc. Don't Work on RPI PICO W
- Investigation and Explanation
- How to Fix It?
- What is RPI PICO W and How to SETUP it?
Why Rubber Ducky, PICO Ducky, etc. Don't Work on RPI PICO W
?
The answer is simple: Everyone tries to add a fail-safe or trigger to enable/disable storage
in boot.py
.
But according to CircuitPython documentation, the storage
state can only be triggered once.
boot.py
– This runs only once before the main code executes.
Investigation and Explanation
Here, I’m using boot.py
to manipulate the USB protocol and declare the device as a USB HID to the OS.
boot.py
– USB HID Init
import usb_hid, storage
storage.disable_usb_drive()
usb_hid.enable(usb_hid.Devices.KEYBOARD)
code.py
– The main keystroke or ducky script
import time
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
# Setup keyboard
kyb = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kyb)
# Open Notepad (Windows: Win + R → type 'notepad' → Enter)
kyb.press(Keycode.WINDOWS)
kyb.send(Keycode.R)
kyb.release_all()
time.sleep(0.5)
layout.write("notepad")
kyb.send(Keycode.ENTER)
time.sleep(1)
for i in range(10):
layout.write("Hello World From Pico HID\n")
OLAA! Your own ducky script.
WAIT WAIT!
Like everyone else, you may think:
"I can just add a trigger to switch between HID and USB Mass Storage!"
But here's the twist, my friend!
boot.py
doesn't wait (or delay) for GPIO-related tasks.
Even if you add a delay, it skips it.
If anything goes wrong inboot.py
, it automatically falls back to USB Mass Storage mode by default.
How to Fix It?
There are two ways to fix this:
Internal Communication (RECOMMENDED)
Here you have more reliable options to communicate between boot.py
and code.py
.
I recommend using microcontroller.nvm
which helps toggle state between the two scripts.
microcontroller.nvm
– Persistent Non-Volatile Memory.
Example:
boot.py
import microcontroller
microcontroller.nvm[0] = 1 # Use 1 or 0 depending on mode
code.py
import microcontroller
if microcontroller.nvm[0] == 1:
print("USB drive was enabled")
else:
print("USB drive was disabled")
External Communication
You can also use a simple state.txt
file to read/write the current state.
This allows both scripts to enable or disable USB Mass Storage based on that value.
Example:
Get state from file
def getState():
with open("state", "r") as f:
return f.read().replace("\n", "")
Set state to file
def setState(bool_val):
with open("state", "w") as f:
f.write(str(bool_val))
What is RPI PICO W and How to SETUP it?
Hello Beginners!
- RPI – Raspberry Pi
There are two ways to use Python on your RPI PICO W:
- CircuitPython – Easy, stable, and beginner-friendly.
- MicroPython – Gives full control. A bit tricky at first but easy once understood.
In simple terms:
- CircuitPython is like Ubuntu for RPI-based microcontrollers.
- MicroPython is like Arch Linux for RPI-based microcontrollers.
🚀 Speedrun: Setup Process
- Download the CircuitPython
.uf2
file from the CircuitPython website. - Download
nuke.uf2
from CircuitPython or the Raspberry Pi website. - Download the latest CircuitPython RPI PICO W bundle and unzip it.
- While plugging in your PICO to your PC, hold the
BOOTSEL
button untilRPI-RP2
shows up in File Explorer. - Copy
nuke.uf2
to theRPI-RP2
drive. - WAIT 2 seconds. It will eject and reconnect automatically.
- Now, copy the CircuitPython
.uf2
file toRPI-RP2
. -
WAIT again—this time it will show as
CIRCUITPY
. - From the CircuitPython bundle, find the
usb_hid
folder and copy it to your PICO. - Copy your
code.py
andboot.py
into the CIRCUITPY drive. - OLAA! DONE!
NOTE: I'm still exploring better solutions to improve this further.
If you have any suggestions or ideas, please comment down below!
Author: Junaid
Sources:
Top comments (0)