Trim on the Framework Expansion Cards

To handle trim on framework expansion cards, you can adjust udev rules:

cat << EOF | sudo tee /etc/udev/rules.d/42-framework-storage.rules
ACTION=="add|change", SUBSYSTEM=="scsi_disk", ATTRS{idVendor}=="13fe", ATTRS{idProduct}=="6500", ATTR{provisioning_mode}="unmap"
ACTION=="add|change", SUBSYSTEM=="scsi_disk", ATTRS{idVendor}=="32ac", ATTRS{idProduct}=="0005", ATTR{provisioning_mode}="unmap"
ACTION=="add|change", SUBSYSTEM=="scsi_disk", ATTRS{idVendor}=="32ac", ATTRS{idProduct}=="0010", ATTR{provisioning_mode}="unmap"
EOF

If you don’t want to restart, follow that with:

sudo udevadm control --reload-rules
sudo udevadm trigger

And that works.

However, under kernel 7.0 I noticed that unplugging and repluggin device would disable trim (as checked with lsblk -D). To be honest, this might have been happening under older kernel too and I just didn’t notice. Regardless, I needed a solution.

To cut a long story short, my solution was to manually trigger udevadm 2 seconds after USB device has been added. Not the most elegant solution, but it does work.

cat << EOF | sudo tee /etc/udev/rules.d/42-framework-storage.rules
ACTION=="add|change", SUBSYSTEM=="scsi_disk", ATTRS{idVendor}=="13fe", ATTRS{idProduct}=="6500", ATTR{provisioning_mode}="unmap"
ACTION=="add|change", SUBSYSTEM=="scsi_disk", ATTRS{idVendor}=="32ac", ATTRS{idProduct}=="0005", ATTR{provisioning_mode}="unmap"
ACTION=="add|change", SUBSYSTEM=="scsi_disk", ATTRS{idVendor}=="32ac", ATTRS{idProduct}=="0010", ATTR{provisioning_mode}="unmap"
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="32ac", ATTR{idProduct}=="0005", RUN+="/bin/sh -c 'sleep 2; udevadm trigger'"
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="32ac", ATTR{idProduct}=="0010", RUN+="/bin/sh -c 'sleep 2; udevadm trigger'"
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="13fe", ATTR{idProduct}=="6500", RUN+="/bin/sh -c 'sleep 2; udevadm trigger'"
EOF

DaVinci Resolve 18 on Ubuntu 23.10 with Intel GPU

While I am not really a video editing guy I do occassionally play with DaVinci Resolve. Unfortunately, installation was not really straightforward under Ubuntu. Even worse, as I switched to AMD laptop with internal GPU, Resolve didn’t work at all.

As one of those video editing opportunities arose, I decided to try my luck on Kubuntu 26.04. Since this OS is quite newer than my current DaVinci resolve machine (Ubuntu 24.04), I decided to scratch previous procedure and try installation from scratch. Once basic install is done, I can figure which libraries are missing and need adjustment.

So, I downloaded DaVinci Resolve 23.0.1 and executed the following commands:

cd ~/Downloads
unzip DaVinci_Resolve_21.0.3_Linux.zip
chmod +x DaVinci_Resolve_21.0.3_Linux.run
sudo SKIP_PACKAGE_CHECK=1 ./DaVinci_Resolve_21.0.3_Linux.zip

Once install was done, I started the application expecting errors but everything worked just fine. Yes, even on AMD internal GPU.

Now, free version still doesn’t deal with MP4 files and AAC under Linux - darn licenses. Regardless, I am happy to do some pre-conversion before editing rather then dealing with Windows.

Not All Rotates Are Made Equal

If you are dealing with encryption algorithms at all, you will notice bitwise rotate operation is used with regularity. While most processors have it available, not all languages do. For example, C# will force you to use shifting and or alternative, something like this:

(value >> count) | (value << (64 - count))

What might come as a surprise is that this incurs no performance penalty as compared to the native rotate operation. How come?

Well, a couple of years ago issue 4519 dealt with this exact problem. While it was deemed to disruptive to introduce rotate operation to the whole .NET system, it was possible to make JIT smarter. Whenever JIT notices operation pattern above, it will call upon native rotate operation, thus drastically improving performance.

However, since we’re talking about pattern recognition, you need to be careful how you write it. While we can write rotate operation in multitude of ways, not all of them will result in performance improvement. If you want rotate, better stick with the “official” pattern.

Avalonia ShowDialog and a Minimize Button

If you use ShowDialog in Avalonia, you will notice that under KDE/Wayland, window will retain minimize button. Even worse, minimize will hide the window, leaving its owner visible but not clickable. Slightly annoying and user might not even understand immediatelly why clicks on the main window are not working until they restore minimized dialog.

And, try as I might, I found no way to remove minimize box without removing the whole title. Since I was not in the mood to handle titleless windows, the next best thing was to close dialog window on minimize. Of course, detecting when window gets minimized is not really straightforward.

In the end, this is the code I ended up using:

PropertyChanged += (sender, e) => {
  if (e.Property == Window.WindowStateProperty && WindowState == WindowState.Minimized) {
    Dispatcher.UIThread.InvokeAsync(() => {
      WindowState = WindowState.Normal;
      Close();
    });
  }
};

We inject our check into the general PropertyChanged event handling. However, we cannot directly close window here as it will not revert focus to the owner. What we need is to ask dispatcher to invoke our code once UI thread has a spare moment. Then we restore the freshly minimized window, followed by close.

Not great, but not terrible either.

Synchronous Wait for Avalonia Dialog

Ideally, showing Avalonia dialog would be called from async method:

var frm = new Window(owner);
await frm.ShowDialog(this);

And 90% of time you’re good with that.

However, what if we don’t have async method handy? What if we really need to ShowDialog from non-async code?

Well, a bit more convoluted code can be used.

using var source = new CancellationTokenSource();
window.ShowDialog(owner).ContinueWith(t => source.Cancel(),
                                      TaskScheduler.FromCurrentSynchronizationContext());
Dispatcher.UIThread.MainLoop(source.Token);

A bit of handful and not really portable, but it does the job.