This guide shows how to install the `gs_usb` kernel module on Linux. The steps work on both x86-64 and ARM64.
> [!info]
> Most Linux distributions ship with the required `gs_usb` kernel module already installed. The driver is included in Linux 3.16 and newer; CAN FD support requires Linux 5.18 or newer, or a distribution kernel with the CAN FD patches backported.
# Check
```shell
modinfo gs_usb
```
If this prints module information, the driver is installed and no further action is required. If it reports `Module gs_usb not found`, continue.
> [!info]
> If `modinfo` fails but `/sys/bus/usb/drivers/gs_usb` exists, the driver is built into the kernel and no action is required.
# Install from Packages
Install the package that provides kernel modules for the running kernel.
| Distribution | Command |
| -------------- | ------------------------------------------------------------------------- |
| Debian | `sudo apt update && sudo apt install --reinstall linux-image-$(uname -r)` |
| Ubuntu | `sudo apt update && sudo apt install linux-modules-extra-$(uname -r)` |
| Fedora | `sudo dnf install kernel-modules-$(uname -r)` |
| RHEL/CentOS 9+ | `sudo dnf install kernel-modules-$(uname -r)` |
| Arch | `sudo pacman -S linux` |
> [!info]
> On Ubuntu, if `linux-modules-extra-$(uname -r)` is not available, use `sudo apt install linux-modules-$(uname -r)` instead. On Arch, use the package for your running kernel, for example `linux-lts`. On Arch Linux ARM, use `sudo pacman -S linux-aarch64` instead.
>
> If the package for the running kernel is no longer available, install the latest kernel package and reboot.
Then load the module:
```shell
sudo modprobe gs_usb
```
If the package is already installed and the module is still missing, the kernel was likely built without `CONFIG_CAN_GS_USB`. Continue to build from source.
# Build from Source
Only use this if your distribution does not provide the module.
> [!info]
> The kernel must have CAN and USB support enabled (`CONFIG_CAN`, `CONFIG_CAN_DEV`, and `CONFIG_USB`).
## Install Build Tools
| Distribution | Command |
| -------------- | ------------------------------------------------------------------------------- |
| Debian/Ubuntu | `sudo apt update && sudo apt install build-essential linux-headers-$(uname -r)` |
| Fedora | `sudo dnf install gcc make kernel-devel-$(uname -r)` |
| RHEL/CentOS 9+ | `sudo dnf install gcc make kernel-devel-$(uname -r)` |
| Arch | `sudo pacman -S base-devel linux-headers` |
> [!info]
> On Arch, install the headers package for your running kernel, for example `linux-lts-headers` or `linux-aarch64-headers`.
## Download the Source
Download the driver source for the running kernel's base version.
```shell
# Extract the base kernel version, for example 6.8.0-45-generic -> 6.8
KVER=$(uname -r | cut -d- -f1 | sed 's/[+~].*//; s/\.0$//')
curl -fLO "https://raw.githubusercontent.com/torvalds/linux/v${KVER}/drivers/net/can/usb/gs_usb.c"
```
> [!tip]
> If the build fails, use the kernel source package from your distribution instead of the mainline source.
## Build the Module
Create a `Makefile` in the same directory.
```make
obj-m += gs_usb.o
```
Build the module from the same directory.
```shell
make -C /lib/modules/$(uname -r)/build M="$PWD" modules
```
## Install the Module
Install only the built module.
```shell
sudo install -D -m 644 gs_usb.ko /lib/modules/$(uname -r)/extra/gs_usb.ko
sudo depmod $(uname -r)
```
> [!warning]
> Do not run `make modules_install`. It can overwrite modules for the running kernel. Install only `gs_usb.ko` as shown.
Load the module.
```shell
sudo modprobe gs_usb
```
> [!warning]
> Modules built from source must be rebuilt after each kernel update. Re-run these steps for the new kernel.
> [!tip]
> If your distribution later provides `gs_usb`, remove the module from `/lib/modules/$(uname -r)/extra/` and run `sudo depmod $(uname -r)`.
# Load at Boot
On most systems, the module loads automatically when the adapter is connected. On systemd systems, to load it at boot regardless:
```shell
echo gs_usb | sudo tee /etc/modules-load.d/gs_usb.conf
```
# Verify
With the adapter connected:
```shell
lsmod | grep gs_usb
sudo dmesg | grep gs_usb
ip link show
```
The adapter should appear as one `can` interface per channel, for example `can0` and `can1`. See [[Working with CAN Bus on Linux]] to configure the interface, or [[Initializing CAN interfaces with networkd]] to configure it at boot.
# Troubleshooting
| Symptom | Cause | Fix |
| ------------------------------------------ | ------------------------------------------- | ------------------------------------------------------------------------- |
| `Module gs_usb not found` | Module not installed for the running kernel | Install the package or build from source |
| `Key was rejected by service` | Secure Boot is enabled | Sign the module or disable Secure Boot |
| `Invalid module format` or `version magic` | Module built for a different kernel | Rebuild against `uname -r` |
| No `can` interface | Adapter not connected or driver not loaded | Check `dmesg` for USB errors and confirm the adapter is listed by `lsusb` |
| CAN FD does not work | Kernel lacks CAN FD support | Use Linux 5.18 or newer, or a kernel with CAN FD support |
> [!warning]
> If Secure Boot is enabled, unsigned modules will not load. Sign the module with a Machine Owner Key (MOK); disabling Secure Boot is not recommended. See [Kernel module signing](https://docs.kernel.org/admin-guide/module-signing.html).
# References
- [Linux kernel - CAN drivers](https://docs.kernel.org/networking/can.html)
- [Linux kernel - gs_usb driver](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/can/usb/gs_usb.c)
- [Linux kernel - Module signing](https://docs.kernel.org/admin-guide/module-signing.html)