Testing out arm64 with openSUSE Tumbleweed on Odroid C2. The installation is pretty simple. Follow the steps to prepare the micro-sd card. The latest image can be found here.
The device tree of openSUSE seems a bit different from other distributions. e.g.:
- temperature: /sys/devices/platform/scpi/scpi:sensors/hwmon/hwmon0
- blue LED: /sys/devices/platform/leds/leds/c2:blue:alive
Thursday, January 18, 2018
Sunday, October 8, 2017
Enable FIDO U2F on Linux
By default, only root can access the FIDO U2F device on Linux. To change this:
- Insert the U2F device. Note the device number and execute the following command to print out the info. e.g.
sudo udevadm info -a /dev/usb/hiddev1
- Take note of the attributes. e.g. for my HyperFIDO device:
......
ATTRS{idProduct}=="0880"
ATTRS{idVendor}=="096e"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="HS"
ATTRS{maxchild}=="0"
ATTRS{product}=="HyperFIDO Token"
......
- Create a new rule file under /etc/udev/rules.d and grant permission to all users. e.g. create a file named "10-fido-key.rules" and add the followings:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0880", TAG+="uaccess"
- Re-insert the U2F device.
Sunday, October 1, 2017
Let's Encrypt with Google Cloud Platform
Assuming you already have an application deployed to Google App Engine with a custom domain. Now you want to add https with certificates generated from Let's Encrypt. Here are the steps on how to do it.
(1) Setup your Let's Encrypt client:
git clone https://github.com/letsencrypt/letsencrypt
(2) Generate the certificate. For example, to get a certificate for www.acme.com:
sudo ./letsencrypt-auto certonly --manual -d www.acme.com
Answer a few questions and the script will pause. You will then need to upload a validation file to www.acme.com to confirm that you indeed own the domain.
_Pwd8uL9_Joz0O2HNlbyb5nBnrcqvmGj02gX2PfJYhw
and the content is _Pwd8uL9_Joz0O2HNlbyb5nBnrcqvmGj02gX2PfJYhw.XOAQHxnBJFCW1KHWhsYsaRmc_BaKnwNpuNYbS8o2gdY
In your app.yaml file, include the /.well-know folder as static content:
handler:
......
- url: /.well-known
static_dir: .well-known
......
Then deploy your app:
gcloud app deploy app.yaml
(4) (Optional) Test the URL with your browser that the validation file is deployed successfully.
(5) Go back to the console where the Let's Encrypt client is paused. Press Enter to continue the execution. If everything worked out, the certificate and private key will be generated.
(6) Deploy the certificate to GCP. In your browser, go to the GCP console > App Engine > Settings. Select "SSL certificates". Click "Upload a new certificate".
Dump the content of the certificate and paste it in the text area:
sudo cat /etc/letsencrypt/live/www.acme.com/fullchain.pem
For the private key, you will need to convert the format to RSA before pasting:
sudo openssl rsa -in /etc/letsencrypt/live/www.acme.com/privkey.pem
Finally, check the box to enable this certificate with your custom domain.
(1) Setup your Let's Encrypt client:
git clone https://github.com/letsencrypt/letsencrypt
(2) Generate the certificate. For example, to get a certificate for www.acme.com:
sudo ./letsencrypt-auto certonly --manual -d www.acme.com
Answer a few questions and the script will pause. You will then need to upload a validation file to www.acme.com to confirm that you indeed own the domain.
Create a file containing just this data:(3) Create and upload the file to App Engine. Create the folder .well-know/acme-challenge in your application tree. Then create the specified file and content. In this example, the file name is
_Pwd8uL9_Joz0O2HNlbyb5nBnrcqvmGj02gX2PfJYhw.XOAQHxnBJFCW1KHWhsYsaRmc_BaKnwNpuNYbS8o2gdY
And make it available on your web server at this URL:
http://www.acme.com/.well-known/acme-challenge/_Pwd8uL9_Joz0O2HNlbyb5nBnrcqvmGj02gX2PfJYhw
-------------------------------------------------------------------------------
Press Enter to Continue
_Pwd8uL9_Joz0O2HNlbyb5nBnrcqvmGj02gX2PfJYhw
and the content is _Pwd8uL9_Joz0O2HNlbyb5nBnrcqvmGj02gX2PfJYhw.XOAQHxnBJFCW1KHWhsYsaRmc_BaKnwNpuNYbS8o2gdY
In your app.yaml file, include the /.well-know folder as static content:
handler:
......
- url: /.well-known
static_dir: .well-known
......
Then deploy your app:
gcloud app deploy app.yaml
(4) (Optional) Test the URL with your browser that the validation file is deployed successfully.
(5) Go back to the console where the Let's Encrypt client is paused. Press Enter to continue the execution. If everything worked out, the certificate and private key will be generated.
(6) Deploy the certificate to GCP. In your browser, go to the GCP console > App Engine > Settings. Select "SSL certificates". Click "Upload a new certificate".
Dump the content of the certificate and paste it in the text area:
sudo cat /etc/letsencrypt/live/www.acme.com/fullchain.pem
For the private key, you will need to convert the format to RSA before pasting:
sudo openssl rsa -in /etc/letsencrypt/live/www.acme.com/privkey.pem
Finally, check the box to enable this certificate with your custom domain.
Wednesday, September 6, 2017
OpenSUSE Tumbleweed on AMD APU Kabini
In order to have Tumbleweed GUI working on Kabini, one needs to install the kernel-firmware package.
Recently moved my Linux workstation to an old AMD APU platform with Kabini (Athlon 5350). The installation completed successfully, but the console goes blank and X cannot use the radeon driver and fallback to VESA.
After some digging, found that although the radeon and amdgpu modules are loaded, there are error messages in dmesg saying that some firmwares cant be loaded.
The problem can be easily fixed by installing the kernel firmware:
sudo zypper install kernel-firmware
Saturday, September 2, 2017
Shrinking the Linux guest storage file of VirtualBox
Shrinking the dynamic storage file of VirtualBox used to be tedious. First need to zero out the free space in the guest and then compacting the file from host.
With Linux supporting TRIM and VirtualBox supporting DISCARD, it can be done much easier within the guest.
First, on the host, prepare the storage file with DISCARD support:
VBoxManage storageattach "Ubuntu server" --storagectl "SATA" --port 0 --discard on --nonrotational on
- "Ubuntu server" is the VM name
- use "--storagectrl" and "--port" to specify the storage controller
Then whenever the storage file needs to be compacted, execute fstrim in the guest. e.g.
sudo fstrim -v /
where "/" is the mount point.
With Linux supporting TRIM and VirtualBox supporting DISCARD, it can be done much easier within the guest.
First, on the host, prepare the storage file with DISCARD support:
VBoxManage storageattach "Ubuntu server" --storagectl "SATA" --port 0 --discard on --nonrotational on
- "Ubuntu server" is the VM name
- use "--storagectrl" and "--port" to specify the storage controller
Then whenever the storage file needs to be compacted, execute fstrim in the guest. e.g.
sudo fstrim -v /
where "/" is the mount point.
Tuesday, June 20, 2017
Compiling Nvidia 340.102 driver for Linux 4.11.x kernel
Further to the patch for compiling 340.102 driver on 4.10.x kernel, to compile for 4.11.x kernel, add the following patch on kernel/nv-drm.c too.
From:
static int nv_drm_unload(
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
static int nv_drm_unload(
#else
static void nv_drm_unload(
#endif
struct drm_device *dev
)
From:
static int nv_drm_unload(
struct drm_device *dev
)
to
)
to
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
static int nv_drm_unload(
#else
static void nv_drm_unload(
#endif
struct drm_device *dev
)
Saturday, June 17, 2017
A Java stream approach on testing triangular Fibonacci numbers
Read this interesting blog post on testing triangular Fibonacci numbers. And I decided to implement a similar test in Java.
First, a Java Stream to produce triangular numbers.
public static Stream<BigInteger> stream() {
return Stream
.iterate(
BigInteger.ONE,
i -> i.add(BigInteger.ONE))
.map(i -> i.multiply(i.add(BigInteger.ONE)).divide(TWO));
}
And a Stream for Fibonacci sequence.
public static Stream<BigInteger> stream() {
return Stream
.iterate(
new BigInteger[] { BigInteger.ONE, BigInteger.ONE },
p -> new BigInteger[] { p[1], p[0].add(p[1]) })
.map(p -> p[0]);
}
Now, a simple and naive way to test for a triangular Fibonacci number is to loop the Fibonacci sequence while testing for the number's existence in the stream of triangular numbers.
Iterator<BigInteger> fib = FibonacciNum.stream().limit(TEST_LIMIT).iterator();
Iterator<BigInteger> tri = TriangularNum.stream().iterator();
BigInteger t = tri.next();
List<BigInteger> result = new ArrayList<BigInteger>();
while (fib.hasNext()) {
BigInteger f = fib.next();
while (t.compareTo(f) <= 0) {
if (t.equals(f)) {
result.add(t);
}
t = tri.next();
}
}
But since the Fibonacci sequence grows so quickly, it is a waste of CPU time to generate all those triangular numbers. A quicker way is to ditch the triangular number stream and implement a test function for triangular number. We then use that function to filter the Fibonacci stream.
List<BigInteger> result = FibonacciNum
.stream()
.limit(TEST_LIMIT)
.parallel()
.filter(f -> TriangularNum.isTriangular(f))
.distinct()
.sorted()
.collect(Collectors.toList());
And with the fast approach, on an i5 4210 machine, testing the first 50,000 Fibonacci numbers will take 93s.
See source below or on GitHub.
First, a Java Stream to produce triangular numbers.
public static Stream<BigInteger> stream() {
return Stream
.iterate(
BigInteger.ONE,
i -> i.add(BigInteger.ONE))
.map(i -> i.multiply(i.add(BigInteger.ONE)).divide(TWO));
}
And a Stream for Fibonacci sequence.
public static Stream<BigInteger> stream() {
return Stream
.iterate(
new BigInteger[] { BigInteger.ONE, BigInteger.ONE },
p -> new BigInteger[] { p[1], p[0].add(p[1]) })
.map(p -> p[0]);
}
Now, a simple and naive way to test for a triangular Fibonacci number is to loop the Fibonacci sequence while testing for the number's existence in the stream of triangular numbers.
Iterator<BigInteger> fib = FibonacciNum.stream().limit(TEST_LIMIT).iterator();
Iterator<BigInteger> tri = TriangularNum.stream().iterator();
BigInteger t = tri.next();
List<BigInteger> result = new ArrayList<BigInteger>();
while (fib.hasNext()) {
BigInteger f = fib.next();
while (t.compareTo(f) <= 0) {
if (t.equals(f)) {
result.add(t);
}
t = tri.next();
}
}
List<BigInteger> result = FibonacciNum
.stream()
.limit(TEST_LIMIT)
.parallel()
.filter(f -> TriangularNum.isTriangular(f))
.distinct()
.sorted()
.collect(Collectors.toList());
Testing the first 70 Fibonacci numbers, the time diff between the two approaches is huge (24ms vs 4s).
See source below or on GitHub.
Saturday, May 6, 2017
Compiling Nvidia 340.102 driver for Linux 4.10.x kernel
Upgraded my Tumbleweed to kernel 4.10.x and Nvidia 340 driver won't build. Until Nvidia fix it, here are steps to patch the 340.102 driver to make it works.
Download the 340.102 driver from Nvidia:
http://www.nvidia.ca/object/unix.html
Unpack the driver:
./NVIDIA-Linux-x86_64-340.102.run -x
Apply patch for kernel 4.9.x:
https://pkgs.rpmfusion.org/cgit/nonfree/nvidia-340xx-kmod.git/tree/4.9.0_kernel.patch
Apply patch for kernel 4.10.x:
https://raw.githubusercontent.com/MilhouseVH/LibreELEC.tv/8d3956f72d79ea3648b19f4c705a38307bb03efb/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-kernel-4.10.patch
Proceed to install. Note that the unified memory module can't be built with this patch, so we are disabling it:
sudo ./nvidia-installer --no-unified-memory
Download the 340.102 driver from Nvidia:
http://www.nvidia.ca/object/unix.html
Unpack the driver:
./NVIDIA-Linux-x86_64-340.102.run -x
Apply patch for kernel 4.9.x:
https://pkgs.rpmfusion.org/cgit/nonfree/nvidia-340xx-kmod.git/tree/4.9.0_kernel.patch
Apply patch for kernel 4.10.x:
https://raw.githubusercontent.com/MilhouseVH/LibreELEC.tv/8d3956f72d79ea3648b19f4c705a38307bb03efb/packages/x11/driver/xf86-video-nvidia-legacy/patches/xf86-video-nvidia-legacy-kernel-4.10.patch
Proceed to install. Note that the unified memory module can't be built with this patch, so we are disabling it:
sudo ./nvidia-installer --no-unified-memory
Sunday, January 8, 2017
Face recognition with OpenCV 3.x
Here is another experiment with OpenCV face detection and recognition. Full source code is available on GitHub.
The picture below is the recognition program running on my Windows laptop and the webcam is feeding live images to the program. My phone is in front of the webcam showing a photo.
The face recognizer was trained with ~10 photos each for Obama, Trump, and Trudeau that I found on internet.
To increase the accuracy, a simple transformation step was added to level the face images when training the recognizer.
The picture below is the recognition program running on my Windows laptop and the webcam is feeding live images to the program. My phone is in front of the webcam showing a photo.
The face recognizer was trained with ~10 photos each for Obama, Trump, and Trudeau that I found on internet.
To increase the accuracy, a simple transformation step was added to level the face images when training the recognizer.
Saturday, December 31, 2016
OpenCV face detection on UDOO with Arch Linux
A few years ago, tried to run face detection on BBB. This time trying it on the more powerful UDOO platform. Some minor code changes:
- Move from Python module cv to cv2
- OpenCV 3.x
My UDOO is running Arch Linux with kernel 4.9. Note that the libGL included in "imx-gpu-viv-fb" doesn't work properly with OpenCV. Switching to "mesa-libgl" solved the issue.
$ sudo pacman -Sy mesa-libgl opencv python2-numpy
A Logitech C200 USB web camera is plugged in and detected automatically.
$ lsusb
Bus 001 Device 003: ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter
Bus 001 Device 004: ID 046d:0802 Logitech, Inc. Webcam C200
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ lsusb -s 001:004 -v | egrep "Width|Height"
Couldn't open device, some information will be missing
wWidth 640
wHeight 480
wWidth 160
wHeight 120
wWidth 176
wHeight 144
wWidth 320
wHeight 240
......
The camera supports maximum resolution of 640x480. But reducing the capture to 320x240 (line 9-10) produces a smoother video on UDOO.
The refresh rate is approximately 30fps. Change the waitKey parameter (line 58) to adjust it.
- Move from Python module cv to cv2
- OpenCV 3.x
My UDOO is running Arch Linux with kernel 4.9. Note that the libGL included in "imx-gpu-viv-fb" doesn't work properly with OpenCV. Switching to "mesa-libgl" solved the issue.
$ sudo pacman -Sy mesa-libgl opencv python2-numpy
A Logitech C200 USB web camera is plugged in and detected automatically.
$ lsusb
Bus 001 Device 003: ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter
Bus 001 Device 004: ID 046d:0802 Logitech, Inc. Webcam C200
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ lsusb -s 001:004 -v | egrep "Width|Height"
Couldn't open device, some information will be missing
wWidth 640
wHeight 480
wWidth 160
wHeight 120
wWidth 176
wHeight 144
wWidth 320
wHeight 240
......
The camera supports maximum resolution of 640x480. But reducing the capture to 320x240 (line 9-10) produces a smoother video on UDOO.
The refresh rate is approximately 30fps. Change the waitKey parameter (line 58) to adjust it.
Subscribe to:
Posts (Atom)
