To head this off before I get questions: yes, dear Reader, it is 2021, and I am writing about a floppy disk drive. Specifically, a USB floppy disk drive that’s connected to a Raspberry Pi.

A USB floppy drive with googly eyes

His name is Stefan

This is a story about tracing a weird behaviour in a complex computer system.

I’ve always thought floppy disks were super cool. They’re really pleasingly tactile; they have this super good tchünk sound when you insert and eject disks, they’re able to hold a whole 1.44 MB of data1, and they have a nice use-metaphor – you can tell when your computer is reading and writing to them because they’re hella noisy, and I think that’s actually a really useful property for removable media. Remember how nice it was to insert a VHS tape? At a certain point the player starts pulling the cassette out of your hand, and it’s clear that you’re agreed on how the relationship works. There’s no USB superposition, there’s no futzing around with drivers or waiting for things to show up in the operating system; you get a kind of gritty, visceral feedback right from the first touch.

I like the tactile-ness of floppy disks so much that back in 2018 I started building an audio player based on the metaphor:

An early prototype

Floppy disk drives don’t really support media detection though; there’s no way of knowing that a disk is in the drive without trying to read a sector from it. So for this project, my method of checking for disk presence was originally to:

The disk was super quiet when reading the same file over and over again. This was an accident, but I was grateful for it considering this was going to be a music player. I’d put the quietness down to the fact that the file I’m reading is very small (~100 bytes; it’s just a link to a Spotify playlist), and fits on one magnetic track (~9kb). My hypothesis was, moving the read head between tracks is the noisy part, spinning the disk is comparatively quiet. But then, I also noticed that the floppy disk drive was making a weird clicking sound when there wasn’t anything in there.

click click click

Oh, it’s probably because I’m trying to read from the disk in a loop! I guess it’s looking for the file, but doesn’t know where it is and has to poke around the disk a bit.

I closed my program. But then the clicking sound stayed. Why is it clicking?

Step 1: Google it

Let’s describe our symptoms to Google:

Google Search: Floppy drive reading constantly.

Oh, these are all results for Windows. Let’s try again:

Google Search: Floppy drive reading constantly linux

After reading, googling, reading some more, here’s what I learned: the linux kernel will “poll” drives with removable media to check that they haven’t been removed, and apparently you can turn that off by using something called “udev” rules. I didn’t know anything about those, so I read up on the basics of udev, and along the way discovered that udev is mostly just for configuring stuff automatically when a device connects to the system. It turns out we don’t need udev for short-term changes and testing, and I can just write settings directly to the kernel2 🤯.

So, let’s turn off the probing for this disk:

# As root, assuming /dev/sda is the path to the floppy disk:
echo 0 >/sys/`udevadm info --query=path /dev/sda`/events_poll_msecs

Hmmm, ok! Turning off the probing seems to make everything quiet. Amazing… but now my program thinks that the disk is still inserted even when it’s not:

oh noooooo

Huh. I’ve broken my disk detection logic. That sounds like a caching problem.

Part 2: Google, again

Back to Google:

Google Search: Mount disk without cache linux ('linux' emphasised)

Not today, Satan!

Again, summarising the situation:

And then I put two and two together: the disk cache was the reason why reading the same file over and over again was quiet.

So the information we have at this point:

So I started wondering, why does the kernel probing make the nasty clicking sound? What is it doing to find out if there’s a disk? Someone on a forum post somewhere mentioned that there was a “quiet probe mode” for some other type of floppy disk, so I wondered if I had the option to do something similar.

If this polling is happening in the kernel, I guess that means it’s time to… read the kernel source?

Part 3: Kernel diving

Way back when I was an Android developer, I discovered reading the source code as a debugging strategy. Documentation is great, but it’s not always available, and it can never cover all the side effects comprehensively – it’s rare that method documentation contain notes like “Warning! Some devices might make a whole bunch of noise when you call this”.

First, let’s download the source for the linux version we’re using.

# Print kernel version
$ uname -r
5.4.51-v7+
$ git clone --depth 1 --branch v5.4 git@github.com:torvalds/linux.git

Now, the kernel has a lot of code, so let’s narrow down our search space by printing the kernel logs, and then watching for messages when we insert / remove disks. We’ll want to crank up the verbosity of the kernel logs first.

# Crank to MAX VERBOSITY (on my system, this will give us up to
# INFO, but we'd need to recompile the kernel if we wanted DEBUG)
echo 7 | sudo tee /proc/sys/kernel/printk
# Now print and watch the kernel logs
dmesg -w

Now:

I got logs like this. I’ve annotated them with what I did to the disk that might’ve triggered the event:

📝 connect drive over USB
[  160.808721] usb 1-1.2: new full-speed USB device number 7 using dwc_otg
[  160.942361] usb 1-1.2: New USB device found, idVendor=03ee, idProduct=6901, bcdDevice= 2.00
[  160.946707] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  160.949088] usb 1-1.2: Product: MITSUMI0
[  160.951423] usb 1-1.2: Manufacturer: MITSUMI0
[  160.955302] usb-storage 1-1.2:1.0: USB Mass Storage device detected
[  160.988923] scsi host0: usb-storage 1-1.2:1.0
[  162.051822] scsi 0:0:0:0: Direct-Access     MITSUMI  USB UFDD 061M    0.00 PQ: 0 ANSI: 0 CCS
[  162.056954] sd 0:0:0:0: Attached scsi generic sg0 type 0
[  162.115750] sd 0:0:0:0: Power-on or device reset occurred
[  162.307854] sd 0:0:0:0: [sda] Attached SCSI removable disk
📝 insert disk
[  180.035797] sd 0:0:0:0: [sda] 2880 512-byte logical blocks: (1.47 MB/1.41 MiB)
[  181.087570]  sda:
📝 ran pmount command
[  218.367027] FAT-fs (sda): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
📝 ejected disk
[  265.700035] VFS: busy inodes on changed media or resized disk sda

Hmmm, this wasn’t as useful as I expected, but there’s already a bunch of kernel modules listed here that we can search the source for (usb, usb-storage, scsi, sd).

In addition, through my adventures with udev, I’d learned that you can find out info about your USB devices using the (appropriately named) usb-devices command:

$ usb-devices
...
T:  Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=03ee ProdID=6901 Rev=02.00
S:  Manufacturer=MITSUMI0
S:  Product=MITSUMI0
C:  #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=98mA
I:  If#=0x0 Alt= 0 #EPs= 3 Cls=08(stor.) Sub=04 Prot=00 Driver=usb-storage

This gives us another note: the driver for this device is the ‘usb-storage’ driver, not the floppy driver.

The output I got from all this was enough that I was able to Ctrl+F my way through the source until I found a starting point.

Part 3½: A whirlwind tour of USB floppy drivers in the kernel source

Like onions, parfaits, and ogres, linux drivers have layers. It turns out that this USB-connected floppy drive is a daisy-chained set of drivers / kernel modules:

Amazing! I then remembered that I’d modified the /sys/.../events_poll_msecs file to turn kernel polling on and off, and wondered if that was actually defined in the kernel, and if it could give me a pointer to the poll code?

Ok! That’s… hmm. It looks like all the computer is doing is saying to the USB floppy drive “HEY. Are you ready?” And then the floppy drive is saying

BRZT BRZT BZRT

no,

not yet sorry..

It seems like we’re not going to be able to make it quieter without looking at the floppy firmware, and that feels like something I don’t wanna touch.


Hmmm. Ok. Let’s recheck everything we know:

At this point, I was pretty stumped – I was sitting at my desk, staring blankly at the Raspberry Pi and attached floppy drive.

staring blankly at the floppy drive

And then it hit me:

Part 4: A dirty, dirty hardware solution

Look how much the frame travels when you insert a disk! That’s like, a good 5 mm!

also that sound is really satisfying

Hmm… I wonder if we could just… glue a switch onto the case and read that from the Raspberry Pi’s GPIO pins?

A floppy disk drive with the case removed, and a keyswitch glued on top upside down such that it will register disk insertion

✨ Engineering ✨
This is a keyswitch stuck upside-down onto the floppy drive.
Please excuse whatever the heck is going on with the soldering.

And then let’s wire it to the Raspberry Pi:

The floppy disk drive is connected to the Raspberry Pi via GPIO. The Raspberry Pi also has googly eyes.

Now, my program’s going to use the Raspberry Pi’s GPIO as a trigger for detecting when the floppy disk is inserted or ejected.

yesssssssssssss

There are some huge advantages to this:

There are also some disadvantages:

Obscure, but knowable, magic

Now I’ve got a floppy disk drive that does its work quietly and gives me signals about when disks are inserted or not, and after three days of digging through source code and trying to understand parts of linux, I ended up solving it by gluing on an upside-down keyswitch.

I guess the lesson here is: Computers may be magic, and maybe even obscure magic, but they’re certainly not unknowable magic. And even then, sometimes the best thing you can do is just bypass all the magic and implement a cheap parlour trick 🤹🏻‍♂️.


  1. That’s enough to fit most classic works of Russian literature, or, like, a 20th of the New York Times homepage! ↩︎

  2. I cannot remember where I learned about this initially, but Bite-Sized Linux is a good intro to some adjacent concepts! ↩︎

  3. SCSI is an old-school protocol that’s been used for storage since I remember computers. I had no idea that USB storage secretly used SCSI protocols under the hood, but computers are full of shenanigans like this! ↩︎

  4. If you’ve ever wondered what the sd in /dev/sda stands for, it’s SCSI Disk! ↩︎

  5. This is vague because I didn’t need to dive in deeper here, but Block Device Drivers is a great tutorial about how block devices work. ↩︎

  6. This method also has an amazing comment that explicitly references the Imoega Jaz 1G as a device that it’s trying to accomodate. ↩︎