Thursday, January 26, 2017

Reading Samsung SSDs temperature using hddtemp tool

Hddtemp is a very simple tool that queries SMART-capable memory drives for temperature values. A quick note: SMART is a technology that lets you monitor stats about the health of disk. Each parameter has a code and an associated value. Software queries for a specific code and gets the corresponding value. Seems easy, right?

Now, hddtemp is pretty simple to use too. assuming your drive is /dev/sda:

#installation on debian-based systems
sudo apt install hddtemp

#usage
sudo hddtemp /dev/sda

If you get an error instead of just the name of your device and the temperature, there are two possible explanations:
  • The drive hasn't a temperature sensor onboard (never say never)
  • The drive doesn't provide temp value on SMART parameter 194.

In SMART, 194 is the code for "Current internal temperature". hddtemp checks parameter 194, unless an alternative code to check for that specific device is known. Those cases are handled by the hddtemp.db, that on Ubuntu is found under /etc/hddtemp.db . 

For SSDs, (at least Samsung ones), the correct smart code to check is 190 (or "Air flow temperature"). So we need a way to tell hddtemp that we know the right code in order to read temperature. 

Run:

sudo gedit /etc/hddtemp.db

Look at the file structure: 4 columns indicate a regex for matching with devices, a code, a 'C' character and an alias. We need to add a line for our Samsung SSD (850 Evo exposes temperature on parameter 190, but maybe your drive uses another code: Google is your friend then!):

#add this line at the bottom of the file, or in the SAMSUNG section for consistency
"SAMSUNG SSD 850 EVO" 190 C "Samsung SSD 850 EVO"

Then, save and close. You don't need to reboot in order to check if now hddtemp works well with your drive, it worked for me.

Some bottom notes: hddtemp is a non-gnu, gpl project hosted on Savannah repo. It is currently quite unmaintained, and it is packed in the repos of most known distributions with very old hddtemp.db, although on internet you can find more up-to-date version of this simple file. You can search or create your updated hddtemp.db and replace the old one in /etc folder if you want.

Monday, November 28, 2016

OpenCL on Ubuntu with Intel Haswell and Nvidia Optimus

OpenCL is a specification aimed to provide a unified way to handle parallel computation on different devices (CPUs, GPUs, FPGAs, DSPs for example but, who knows, every piece of hardware that can do some calculations could suit the purpose of OpenCL with an ad-hoc driver). However, the setup of the platform could be quite difficult, especially if the underlying machine has an heterogeneous set of OpenCL-compatible devices.

Today, we are focusing on a specific configuration: a laptop with both Intel CPU/GPU and a discrete nVidia GPU, managed by the Optimus technology, and Ubuntu 16.04 LTS installed. 

Disclaimer: it seems that, due to Nvidia Optimus, there is no way to use both integrated GPU and discrete GPU at the same time. I haven't tested the combination CPU/discrete GPU yet. So, in this article I'll briefly explain how to install the correct drivers for each device, and then to switch between those from Intel and those from Nvidia.

First: let me explain how an OpenCL host software works. An executable is dynamically linked to a special library, named libOpenCL.so, that is called ICD Loader. ICD stands for Installable Client Library: this loader, on Linux, checks for .icd files in /etc/OpenCL/vendors. Each .icd file is a text file which contains a single line: the full path of a platform-specific OpenCL library. So, on our laptop, we should have at least 2 .icd files: one for Nvidia-specific OpenCL libraries, and one for Intel-related devices instead. The loader let the host program access each available device that is reachable from the given set of libraries/drivers.

In OpenCL terminology, each driver pointed by an .icd file corresponds to an OpenCL Platform, and each device that is supported by that driver is an OpenCL Device.

Installation of core loader, drivers, headers

We need to install the ICD loader and a simple diagnostic/info tool:
sudo apt install -y ocl-icd-libopencl1 clinfo

Next, we install ICDs for Intel and Nvidia GPUs:
sudo apt install -y beignet-opencl-icd nvidia-opencl-icd

Finally, we'll fetch the CPU driver from the Intel website, and we'll manually install it:
wget https://software.intel.com/sites/default/files/managed/8e/5c/SRB3.1_linux64.zip
mkdir temp
unzip SRB3.1_linux64.zip -d ./temp
cd temp
for i in *.tar.xz; do tar -xJf $i; done
sudo rsync -av ./opt /opt
sudo rsync -av ./etc /etc
cd ..
rm -R temp

Now, the final magic: go to the /etc/OpenCL/vendors folder, with root privileges. You'll see two .icd files. Rename the beignet one to intel_gpu.icd and the nvidia one to nvidia_gpu.icd; finally, create a new text file called intel_cpu.icd with the line ".../libintelocl.so"

Try the command "clinfo". It should be end in a segfault or in weird errors naming the X server and something about Dri2 access. If all platforms, (Intel CPU, Intel GPU, Nvidia GPU) are correctly detected, it means that you are luckier than me. In my case (Intel i7-4710MQ and Nvidia GTX 960 on a Clevo barebone 13' laptop), the already-mentioned errors occur.

Now we update the OpenCL headers with the last version from Kronos GitHub Repo:
sudo rm -R /usr/local/include/CL
sudo mkdir /usr/include/CL
sudo wget https://github.com/KhronosGroup/OpenCL-Headers/archive/master.zip -P /usr/include/CL
sudo unzip -j -o /usr/include/CL/master.zip -d /usr/include/CL
sudo rm /usr/include/CL/master.zip
sudo wget https://github.com/KhronosGroup/OpenCL-CLHPP/archive/master.zip -P /usr/include/CL
sudo unzip -j -o /usr/include/CL/master.zip "*input_cl2.hpp" -d /usr/include/CL
sudo mv /usr/include/CL/input_cl2.hpp /usr/include/CL/cl2.hpp
sudo rm /usr/include/CL/master.zip 

Solving troubles with Optimus

The solution is quite simple. If you want to work with intel devices, you have to install the official Nvidia Prime package (it's a kind of switcher between Intel and Nvidia drivers):
sudo apt install -y nvidia-prime

Then, to use OpenCL on Nvidia card:
sudo prime-select nvidia
sudo mv /etc/OpenCL/vendors/intel_cpu.icd /etc/OpenCL/vendors/intel_cpu.icd_disabled
sudo mv /etc/OpenCL/vendors/intel_gpu.icd /etc/OpenCL/vendors/intel_gpu.icd_disabled
sudo mv /etc/OpenCL/vendors/nvidia_gpu.icd_disabled /etc/OpenCL/vendors/nvidia_gpu.icd
# now you have: intel_cpu.icd_disabled, intel_gpu.icd_disabled, nvidia_gpu.icd
clinfo --list   # this should detect correctly only your Nvidia GPU now

Then, to use OpenCL on Intel devices:
sudo prime-select intel
sudo mv /etc/OpenCL/vendors/intel_gpu.icd_disabled /etc/OpenCL/vendors/intel_gpu.icd
sudo mv /etc/OpenCL/vendors/intel_cpu.icd_disabled /etc/OpenCL/vendors/intel_cpu.icd
sudo mv /etc/OpenCL/vendors/nvidia_gpu.icd /etc/OpenCL/vendors/nvidia_gpu.icd_disabled
# now you have: intel_cpu.icd, intel_gpu.icd, nvidia_gpu.icd_disabled
clinfo --list   # this should detect correctly only your CPU and the built-in GPU

Saturday, November 5, 2016

Install a LAN-shared Canon Maxify MB2350 on Ubuntu

Yesterday, I bought a brand new Canon Maxify MB2350. One of the most important features of this device is the capability to connect to the local LAN/WLAN, and two-sides printing. I use linux for everyday tasks, along with more academic reasons, and I made a big mistake: I didn't check for Linux compatibility before buying.
So, how to configure the Canon Maxify MB2350 on linux (in particular, Ubuntu 16.04)? After some headache, I partially solved my problem.

Enable basic support for LAN printing

Official Linux drivers (rpm/deb/sources) are usually provided on the product's support page on Canon's website. While digging in the net, I realized that, depending of the region of the support site (Asia,USA,Europe, and more specific versions like Italy), different versions were provided, or none at all! On Italian support page, for example, the proposed version is 5.0. I found that the most recent one is 5.30. The name of the driver is: "IJ printer driver", here are the links:

Debian packages
Rpm packages
Sources tarball
Documentation

Inspecting the sources, I noticed that some components are GPL-v3 licensed, but they use 2 already-backed libs (included in the archive). So it's not a totally open-source driver, and that will be a pain if Canon decides to discontinue those drivers in the future.
I decided to install directly the provided .deb package instead of compiling from sources. In the debian archive, you'll find an "install.sh", and most guides on the internet would reccomend its execution. I tried, but the script fails to identify the printer in the local network. So, ignore it. Install the right .deb file that you can find in the packages folder instead.
Here's the complete step-by-step procedure:

cd /folder/where/you/downloaded/the/canon/driver
gzip -d cnijfilter2*.tar.gz
tar -xf cnijfilter2*.tar
sudo dpkg -i cnijfilter2*/packages/*  #(the package for the wrong architecture will fail)
system-config-printer
Click on Add printer; in the URI text field, type "cnijbe2://Canon/?port=net&serial=AA-BB-CC-DD-EE-FF", where the last fake field has to be replaced with the printer MAC address; Proceed thru the wizard, selecting "Canon" and "Maxify MB2350" when required;
sudo cups-genppdupdate
sudo reboot

Now, it should print.

Known issues:
  • No two sides printing (see next paragraph) 
  • Error while trying to load paper from tray 2. (no solution yet, sorry)

Enable support for two-sides printing

Look at this sourceforge thread. Those hard-to-find messages helped me a lot. In this moment, the last GutenPrint version on Ubuntu 16.04 is 5.2.11. However, the developer that answered in the linked discussion referred to a fix in the 5.2.12 release of Gutenprint that enables the Maxify 2300 and similar to print two-sided sheets. I downloaded the latest version here.
Here are the needed steps to install the latest build:

sudo apt update
sudo apt install -y gcc libcups2-dev libcupsimage2-dev
cd /folder/where/you/downloaded/the/tarball
tar -xf archive_name.tar.bz2
cd archive_name
./configure --enable-cups-ppds --enable-cups-ppds-at-top-level
make
sudo make install
sudo cups-genppdupdate
sudo reboot

Here's the new, interesting lines we get in the updated /etc/cups/ppd/YOUR_PRINTER_NAME.ppd:

*OpenUI *Duplex/2-Sided Printing: PickOne
*OPOptionHints Duplex: "radiobuttons"
*OrderDependency: 10 AnySetup *Duplex
*StpStpDuplex: 0 1 0 0 255 0.000 0.000 0.000
*DefaultDuplex: None
*StpDefaultDuplex: None
*Duplex None/Off: ">>setpagedevice"
*Duplex DuplexNoTumble/Long Edge (Standard): ">>setpagedevice"
*Duplex DuplexTumble/Short Edge (Flip): ">>setpagedevice"
*CloseUI: *Duplex


What else I've noticed?

CUPS could detect the printer and choose the protocol IPP. If you configure the printer as IPP, it won't work. I think that the port used by the printer is the same of IPP, but the cnijbe2 backend provides a different and vendor-specific communication protocol. The MAXIFY has also scan capabilities. On windows, those are provided thru the WSD (Web Services for Devices) protocol. Sane provides an interface that works on most Canon scanners, such as Pixma series, but this MAXIFY isn't supported. The WSD protocol is standard since windows Vista epoch, but no Linux implementations yet. It's based on HTTP POST requests.

Recommendations

A lot of tutorials tell to add ppas (such as the official Ubuntu Documentation, with old builds for 14.04 LTS) or cloning GitHub repos (with old and abandoned copies of the IJ Driver sources). Ignore those sources, download the latest versions of Gutenprint and IJ Driver.