You’ve already verified the driver is missing:
jetson@192.168.1.115:~$ zcat /proc/config.gz | grep 'CONFIG_USB_HIDDEV'
# CONFIG_USB_HIDDEV is not set
(this is part of the kernel, and the particular content can be created as a loadable module; this allows you to avoid building an entire kernel, and simplifies install; don’t use the install docs for the module, it is simpler than that, but you can use the NVIDIA docs for building a kernel and modules)
Most of the time the kernel is the “/boot/Image
” file. Sometimes though this is stored in other locations, although for an SD card Nano this is all you need to worry about. The location where loadable modules are found (which are part of the kernel, but they can be added or removed as the system runs, and have fewer consequences if they fail) is at this location:
/lib/modules/$(uname -r)/kernel
Just to see what I’m talking about, do this:
cd /lib/modules/$(uname -r)/kernel
apt-get install tree
tree -d
The tree of directories which shows up there will be an exact match to most of the subdirectories in the kernel source code. Modules there are any file with the extension “.ko
” (or a compressed “.ko
” in some cases). If you build that feature/driver in the kernel as a module, then in some subdirectory you will that file named after the feature with the extension “.ko
”.
Kernel build seems difficult, but so much effort has gone into simplifying it that if you’ve done it once, and if you’ve downloaded the kernel source, then it becomes easier.
A newer Jetson release won’t add this since it isn’t added by default. It’s just a driver for a special case. The original Image file is built by NVIDIA. Their official documentation shows how to cross compile it on a Linux host PC (it is also possible to compile it directly on a Jetson if you have enough disk space).
This is not about a “fresh” version. A general explanation is that there are many drivers out in the world which the Linux kernel supports. There are drivers for various items you will probably never have, e.g., custom studio sound mixers, 100 Gb/s backbone network cards, custom touchpad screens, specialty programmable keyboards (for the programming half), lots of video cards you won’t use (do you want all of the AMD video drivers? all of the Matrox drivers for video cards long obsolete?), proprietary dongles to software costing many thousands of dollars, so on. Not even desktop Linux includes those by default.
Disk space on a desktop PC is much more unlimited in comparison to a small embedded system. The choice of what to install by default is more limited due to that more limited disk space. HID raw is a “standard”, and so is HID dev, but almost everyone uses HID raw. HID dev does some extra parsing that most HID applications do themselves. It would be reasonable for NVIDIA to include HID dev by default, but it is actually somewhat rare that someone needs it (I’ve been answering questions on this forum since the TK1 in 2013, and this is the first time I’ve seen anyone request HID dev).
One nice thing about Windows is that when it detects a device which needs a driver, then they have a database of various drivers, and can automatically install it. Windows is no different in the fact that they also do not include the driver, but it is more convenient if the package system automatically installs the driver. Of course, not all devices are plug-n-play, and so even on Windows this would require a manual install of the driver.
Add to this that Linux is open source. A few commands and a bit of time and there is no driver you cannot install. It doesn’t matter if the company which made the hardware or created the software went out of existence long before, you have it. If something goes wrong with Windows, then you need to be on the telephone (if they allow it) to Microsoft, the hardware vendor, the sales partners, so on. I promise you that in the Windows world this is not so easy. If you need to see source code, then Microsoft charges a hefty fee and lots of non-disclosure to see their kernel source code (I remember long ago when I still tolerated Windows being quoted around $100k USD to get what I needed to fix a bug nobody wanted to fix). For developers, Linux makes a lot more sense. For someone just getting started it means there is a learning curve.
So far as new software releases go, the System on a Chip (SoC) the Nano is built on is the TX1. This is quite old. For a long time only the 32-bit ARM CPUs existed, and when 64-bit came out, nobody had ever written 64-bit ARM code. The kernel, the drivers…everything…had to be rewritten. The TX1 has the first 64-bit hardware that was ever used (I think it might have been around the year 2014?). This is how 64-bit met efficient power and physical size. All drivers, 100%, had to be rewritten, although there was a 32-bit compatibility mode (which is terribly slow, to the point of not being worthwhile).
By the time the TX2 got here it was much more refined. That too was long ago. When the Xavier got here the system was much faster and much more complete. Much of the architecture of various parts changed over time. The software got much better. Both TX1 and TX2 were quite old then (this was many years ago as well). About this time the GPU had changed so much, and the performance (even including power use) was so improved that the TK1 (32-bit), TX1 (first 64-bit), and TX2 were maintained, but no new features added (support up to and include L4T R32.x). Up until now the Xavier (L4T R34.x+, current R35.x+) has received all new features, but next major release will exclude anything Xavier. Only Orin will go beyond R35.x. It isn’t advertised, but NVIDIA has been working on the next generation for quite some time.
All of these, all the way back to 32-bit, support HID dev. It just has to be enabled.
Linux itself is something most developers learn to love if and only if they need to get into the lower level. If you only want to download and install, then some distributions (such as Ubuntu) are still fairly well supported. However, whatever is supported must be compiled for the architecture (a desktop PC is amd64/x86_64 architecture, modern Jetsons are aarch64/arm64 architecture). The maintainers don’t put those recompiled version on the ARM servers unless they have that hardware (sometimes there are volunteers to port them). If that were the case, then you could simply install this with an “apt
” command. If this were Windows, you would have no hope to get an ARM version which the vendor does not want to provide. In your case, all you have to do is download source code, configure it, and compile. Then copy a file. This beats paying $100k USD for attention when you’d still have to port it yourself.
Do you have a desktop PC (preferably with Ubuntu 18.04, but most Linux distributions work)? On the Jetson I suggest you write down the output of the command “uname -r
”. Note the suffix, which is probably “-tegra
”.
Then find your L4T release version (Ubuntu plus NVIDIA drivers): “head -n 1 /etc/nv_tegra_release
”.
Go to the document page. Look up your release here:
https://developer.nvidia.com/linux-tegra
I will pretend your release is R32.7.3, but use whatever it actually is. Going to that page you will find the Nano versions of:
- Driver Package (BSP) Sources
- Jetson Nano Developer Kit User Guide
- OR the alternate docs online version “Jetson Linux Developer Guide (online version)”.
Within the documentation the part you want to find is “Kernel Customization”. This explains most of what you need to build a kernel. Ignore the install advice as this is for installing to the flash setup such that the changes occur upon flash; you don’t need to reflash, you just need to copy one file, but you still have to build it.
Download the source code (the Driver Package BSP Sources). The file you get will be an archive of many things. The file name is “public_sources.tbz2
” (trivia: this is a bzip2
compressed tar
archive). The package within this package which you are interested in is the “kernel_src.tbz2
” (another bzip2
tar
archive within an archive; once extracted you can throw out the rest of it).
One way to see the content of an archive:
bunzip2 < public_sources.tbz2 | tar --list (there are options to include
bunzip2directly in the
tar` command, but I’m illustrating combining commands without needing to know lots of options)
To extract kernel_src.tbz2
(you have to include the subdirectory, so it is really “Linux_for_Tegra/source/public/kernel_src.tbz2
”):
bunzip2 < public_sources.tbz2 | tar -xv Linux_for_Tegra/source/public/kernel_src.tbz2
Note that you could do this with options instead of that long command, e.g., the “-j
” option implies bzip2
compression:
tar xvfj public_sources.tbz2 'Linux_for_Tegra/source/public/kernel_src.tbz2'
(you’ll find the root of the source at "`Linux_for_Tegra/source/public/)
Once you have this, you can delete “public_sources.tbz2
”. All you need is the “kernel_src.tbz2
”, and this will be decompressed via:
tar xvfj kernel_src.tbz2
Techinically, you could delete the “kernel_src.tbz2
” now, but I advise saving it. This in turn expands into subdirectories. The directory you will work in now exists, and is:
kernel/kernel-4.9/
This location is normally know as the “TOP” of the tree, and often one will do this:
cd kernel/kernel-4.9/
export TOP=`pwd`
echo $TOP
(you could now reference that location within that terminal as “$TOP
”)
Read the documents on kernel compile. This is where you start. I will say though that the docs cover things you don’t need. Sometimes that is good, other times it just confuses people. You don’t need to build the “Image
” target, but if you only build “modules
”, then you need to propagate configuration throughout the source first (and Image
target does this for you, plus it is something of an acid test for whether it is correct).
The part where most people fail is not understanding to configure first. The configuration “make tegra_defconfig
” does this, but then you’d “make modules_prepare
” before you do anything else. Unfortunately, there is one other detail most people miss, and you must do this prior to either building Image
or modules_prepare
: You must set CONFIG_LOCALVERSION
to “-tegra
”. There are many ways to do this.
Also, one can set up a separate location for intermediate files and keep the original source code pristine and untouched. Read the documents. Here is a bit of a shortcut to documents:
# Compile commands start in $TOP, thus:
cd $TOP
# Create a temporary content output location:
mkdir ~/output
# Set an environment variable to this:
export TEGRA_KERNEL_OUT=~/output
# Do not forget to provide a starting configuration.
make O=$TEGRA_KERNEL_OUT tegra_defconfig
# Now put the CONFIG_LOCALVERSION of "-tegra" in. More than one way.
# For this and this only, I suggest you edit this file:
# ~/output/.config
#
# In that file, find "CONFIG_LOCALVERSION". Set it up to be:
CONFIG_LOCAVERSION="-tegra"
# Now us an editor to look for and enable CONFIG_USB_HIDDEV:
make O=$TEGRA_KERNEL_OUT nconfig
# nconfig has a symbol search function, search for KERNEL_OUT.
# Once found, enable it as a module via the "m" key.
# Save the configuration. You're ready to build Image if you choose,
# but if you build modules, then you need to first propagate the
# configuration.
# Note that the "-j 6" option says to use 6 CPU cores during build. If you
# have 12 cores, then you could use "-j 12". If you have 1 core, then just
# "-j 1".
# Be sure you are at $TOP.
# If building the kernel Image:
make -j 6 O=$TEGRA_KERNEL_OUT Image
# If you did not build Image, but are building modules:
make -j 6 O=$TEGRA_KERNEL_OUT modules_prepare
# To build modules:
make -j 6 O=$TEGRA_KERNEL_OUT modules
# It is good to create a temporary output location for modules. For that:
mkdir ~/modules
export TEGRA_MODULES_OUT=~/modules
# To put modules in "$TEGRA_MODULES_OUT":
make -j 6 O=$TEGRA_KERNEL_OUT INSTALL_MOD_PATH=$TEGRA_MODULES_OUT modules_install
You will find a subdirectory if you “cd $TEGRA_MODULES_OUT
”. Note that “uname -r
” is from the Jetson, and not from the host PC, so you’d have to substitute for what “uname -r
” is on the Jetson:
cd $TEGRA_MODULES_OUT
cd lib/modules/$(uname -r)/kernel
tree -d
Only one of the files in that tree is of interest, and I don’t know the exact file name, but here is a search from that location which can probably find the right file (ask if it isn’t, and I’ll find the exact file name):
find . -type f -iname '*hid*.ko' | grep -i 'dev'
I’m going to pretend the proper file is:
lib/modules/4.9.140-tegra/drivers/usb/something-usbdev.ko
Copy the file "``lib/modules/4.9.140-tegra/drivers/usb/something-usbdev.ko" to your Jetson. Move it to "
/lib/modules/4.9.140-tegra/drivers/usb/" (you'll now find
something-usbdev.kothere). Tell the system to update its list of modules:
sudo depmod -a`
Preferably, reboot, but it might just load and work upon plugin of the device. Whatever that file is, assuming it works, it will show up in the list of modules via lsmod
(only if it is loaded).
The general theme:
- Download and unpack kernel source.
- Make temporary output locations for source and for modules.
- Configure to match the old system. It just happens that the “
tegra_defconfig
”, combined with updating “CONFIG_LOCALVERSION
” to “-tegra
” does this. There are other ways as well.
- Propagate configuration. Either do this by building
Image
, or via modules_prepare
. The latter is slow, but much faster than Image
. This might take hours. The former Image
, even if not using it, if preferable for the first build. I say this because there are errors which you will catch when building Image
which won’t be caught when building modules
.
- Now actually build whatever you are building.
- Send modules to the temporary module location.
- Copy the module
.ko
file to the correct subdirectory of “/lib/modules/$(uname -r)/kernel/
”.
- Update the module list with “
sudo depmod -a
”.
- Enjoy.
- Ask more questions if it doesn’t go well.
All this information seems intimidating. However, you’ll find that the steps make sense after you’ve done it a couple of times. You can then use any driver, from any architecture (sometimes there are hiccups), and without any manufacturer or outside developer needed. Most of the time “it just works”.
Note that sometimes drivers are available via the apt
mechanism, but those only occur in mainline PCs most of the time. Jetsons don’t have a BIOS, and their entire boot setup is custom. Anything related to boot is often not standard, and thus missing automated install via apt
. This is why kernel and drivers might need extra work (they’re often part of boot; that particular driver is not, but the kernel as a whole is).