My approach in writing the driver is to pull small bits of change one at a time
so that I don’t get overwhelmed and to make sure I understand every bit of code
I put in.
Where do we start?
A Bit of Documentation
The first thing you’ll notice when you read any driver source code is the
multi-line comment describing what the driver this source code is written for
including author information, license and any other information relevant to the
driver. Furthermore, at the end of the source file, the same information is
documented1 by the use of MODULE_* macros found in the header linux/module.h.
With this header included, we also add the headers for i2c and iio since this
is an IIO driver with support for the I2C interface. The commit about this
change looks like this:
I2C
ADXL345 supports two communication protocols, the I2C and SPI. I’ll deal with
I2C first and then provide support for SPI later on. Looking up the kernel
documentation found in Documentation/i2c/writing-clients we arrive with this
commit:
Device Probing
Now that we have the necessary structures written and initialized, let’s write
that probe function which is currently missing. According to the IIO developer’s
guide2, we need to allocate an iio_dev structure using devm_iio_device_alloc,
fill-in the indio_dev members3 and finally call the devm_iio_device_register.
Another thing that we need to do is to verify the device by reading through the
DEVID register to confirm the device ID. This is useful if you are to support
other devices on the same driver code. The device ID lets you differentiate
and identify them. Here’s the commit with all those presented:
Hey, Where’s the Remove Function?
The commit on the previous section initially includes a remove function. This
led to my computer hanging when the module is unloaded. If you have been
checking the links to the documentation I included, you’ll notice that I’m using
a different version of iio_device_alloc and iio_device_register where they are
prefixed by devm_*. These are what we call the resource-managed4 functions
and it allows us to free the memory allocated automatically when the device is
detached from the system or when the driver for the device is unloaded. This
means that, in most cases you don’t have to provide a remove function.
Now, the question is when to provide the remove function? This is a question I
actually asked my mentors. Thankfully, Alison explained it to me in detail. If
there is a special shutdown or undoing that needs to be done then you have to
provide the remove function and make use of the regular iio_device_register/
*_unregister instead of the resource-managed one.
What’s Next?
I will talk about raw measurements and scale on the next post. Stay tuned and
thanks for reading!