HacksLinuxThe Project BThe Project CTrainings

Building CDC/ACM driver

Source : https://en.wikipedia.org/wiki/USB_communications_device_class

The USB communications device class (or USB CDC class) is a composite Universal Serial Bus device class. The class may include more than one interface, such as a custom control interface, data interface, audio, or mass storage related interfaces.

This class can be used to implement RS-232 communications on the USB bus via the subclass Abstract Control Model (see https://technet.microsoft.com/en-us/ff537026(v=vs.90)), so an USB device can appear as a traditional RS-232 port in an operating system, if the device is compliant to it.


Why implementing this specific driver :

The fact is, Arduinos are compliant to it.

So, as we want to use an Arduino to embed fun softwares, we need to implement this driver to communicate with it, as it uses standard RS-232 protocol as access interface.

To simplify : the USB CDC-ACM driver emulates a serial port.

Fastly said :

1 – the arduino-cli program just need it to upload embed code into arduino chip

2 – softwares need it to communicate with the chip

3  – virtue : a serial communication is very simple to operate in all programming language


How :

Things could be simple, but the the Lattepanda is not running a Linux distribution which provides the acm driver.

So, we need to compile it as a kernel module.

Fortunately, the kernel sources provides the driver code, and the distribution publisher provides convenient packages to build it.


Step 1 : getting the convenient packages

To compile a kernel module, we need the kernel headers. It’s all the definitions of the functions used by the kernel or third party sources.

The kernel headers are quite like a dictionnary for the modules source code.

Here we go ^^ :

opkg install linux-lib-c-headers-dev
opkg install packagegroup-kernel-module-build


Step 2 : getting the driver source code

Fortunately, the publisher provides the source code of the driver. Why he did not provide already the compiled module, like in the more recent version ? Very convenient mystery.

We just have to download them on github after getting to the directory :

cd /lib64/modules/[distroNameHere]/build/drivers/usb/class

wget https://raw.githubusercontent.com/ni/linux/nilrt/comms-2.0/4.1/drivers/usb/class/cdc-acm.c
wget https://raw.githubusercontent.com/ni/linux/nilrt/comms-2.0/4.1/drivers/usb/class/cdc-acm.h
wget https://raw.githubusercontent.com/ni/linux/nilrt/comms-2.0/4.1/drivers/usb/class/cdc-wdm.c
wget https://raw.githubusercontent.com/ni/linux/nilrt/comms-2.0/4.1/drivers/usb/class/usblp.c
wget https://raw.githubusercontent.com/ni/linux/nilrt/comms-2.0/4.1/drivers/usb/class/usbtmc.c

The command wget downloads all the data from a webpage, so we have to select the raw address of the github files. Otherwise, we’ll get the http code of the webpage files, as github is a full web tool.


Step 3 : building the module

To get further into an important debate, see : https://www.cyberciti.biz/tips/build-linux-kernel-module-against-installed-kernel-source-tree.html

Here, we will not build the kernel entirely. The module is not enough complex to do so, and the process would be too long for our today subject.

The important thing is, we will use the following script named Makefile :

obj-m := cdc-acm.o
KDIR := /lib64/modules/$(shell uname -r)/build
PWD := $(shell pwd)
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

Finally, we can execute the script :

make -f Makefile


Step 4 : load the compiled module

insmod /lib64/modules/[distroNameHere]/build/drivers/usb/class/cdc-acm.ko

A new serial device is now adressed by the operating system at /dev/ttyACM0.

It’s our Arduino !!! 🙂


Conclusion :

The fact that a serial Arduino is now addressable gives us the possibility to load it with some test program… In theory.

If the uploading becomes operational, we will need to test the data communication with the Arduino, its stability and global performance. If so, all the varieties of existing Arduino code could be implemented (wondering wich one I could try…).

The further steps will be the implementation of some industrial low level protocols, and again the verifying of global execution.

If all these steps are crossed, it will be more interesting, and all projects become possibilites :D.

(The finest could say we have just creating a new distribution… but we even don’t really need it -well, it’s too early now)


Thank you,





Leave a Reply

Your email address will not be published. Required fields are marked *