user-space application for tmp102 sensor driver - linux

I have a thermo3 click which has tmp102 sensor.
To read data from it, I have written a user-space application using I2C as follows:
fd = open("/dev/i2c-0", O_RDWR))
ioctl(fd, I2C_SLAVE, 0x48)
read(fd, &buf, 2)
But then I found its driver in linux source code.
So I am wondering:
1) Can I write a user-space application which uses this driver's API's (means using driver's device file)?
2) How I2C user-space application works without using this driver (because this driver is not enabled in my kernel when I was using i2c user-space application) or This is the way I2C works?

1) This is an hwmon device, you don't have a device file to use. Instead the api is in /sys/class/hwmon. In particular, you want to read the /sys/class/hwmon/hwmonX/tempX_input files
2) By using /dev/i2c-0, your are directly communicating on the i2c bus, effectively bypassing any kernel driver. You then have to know the details for any device you use (registers to read and their meaning...) instead of using the generic Linux kernel abstraction.

User Level Application can not interact with hardware. They can communicate by system call (ioctl, open, read and write etc) and Sysfs(sysfs is a virtual file system).
1 :- Your device is hwmom device. Your Driver is "tmp102". Driver Expose these three temp1_input, temp1_max_hyst and temp1_max sysfs entry for user-level application.
SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0);
SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, tmp102_set_temp, 1);
SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
tmp102_set_temp, 2);
You can read /sys/class/hwmom/tmp102/temp1_input sysfs file.
you can read and write these two sysfs file /sys/class/hwmom/tmp102/temp1_max_hyst and sys/class/hwmom/tmp102/temp1_max.
2 :- The files in /dev are actual devices files which UDEV creates at run time.A device file is an interface for a device driver that appears in a file system as if it were an ordinary file. Your driver has expose some other device file. thermal_zone_of_sensor_register(hwmon_dev, 0,hwmon_dev, &tmp102_of_thermal_ops). You have /dev/hwmom_dev node.
User-Level application can't directly communicate any of i2c-device or hardware. Linux kernel has limitation. Application need driver as interface to controle any of device.

Related

How to access an IIO device driver in linux

I a noob to Linux device drivers.
I have an IIO driver with me (for OPT3001 ambient light sensor) , operating over the I2C bus, which has been compiled successfully in the kernel (version 3.18). The device tree is modified to match the compatible field, present in the driver.
The problem is how do I access this driver to get some data in the userspace ?
The driver has some callbacks for read and write registered in a structure. Should I call them directly in my C file ?
you have differents possibilities :
your driver provide a /dev node you can open in you C file.
your driver provide informations through sysfs.
in case of a /dev node, you can have access to file operations (open, read, write, ioctl). you just have to open your file 1 time and each read() call will read the value from the sensor.
in case of sysfs, you should find the file to open/read in /sys/class/...
You can use the userspace API provided by:
#include <linux/i2c-dev.h>
Using it you can open de bus /dev/i2c-X (X=0,1,2,...), set device address using ioctl call, and use read and write operations to read and write to/from the bus.
Also, you can install "i2c-tools" package (apt-get install i2c-tools), to install userspace tools like i2cset, i2cget and i2cdetect, very useful for testing the I2C bus and the device connected to it.

Accessing Linux Drivers

Simply put, can a user space application access device drivers running in kernel mode? If I want to read from the I2C Linux character driver, can a basic C executable (extensionless) do that or do I need to develop a kernel module specifically for that task? If a basic C app can access the I2C character driver, what does that gcc makefile look like?
Yes. User space application can access the kernel driver if the driver is character device or the driver exposing the stream interfaces.
Specific to i2c, user space application can write and reads to the i2c device via sysfs api.
Refer the kernel document here https://www.kernel.org/doc/Documentation/i2c/dev-interface

difference between device file and device driver

I am currently reading the Linux Module Programming Guide and I have stumbled onto two terms that have confused a bit - device files and device driver. Upon goggling these terms I have come across the following-
A device driver is a piece of software that operates or controls a particular type of device.
A device file is an interface for a device driver that appears in a file system as if it were an ordinary file. In Unix-like operating systems, these are usually found under the /dev directory and are also called device nodes.
What I would like to know is -
1) Are device files an interface between user space programs and the device driver?
2) Does the program access the driver in the kernel via the appropriate device special file?
eg, when using say spidev char dev file, does that allow my userspace program to interact with spi.c and omap2_mcspi.c etc using simple read, write and ioctl calls?
One of the primary abstractions in Unix is the file (source):
Programs, services, texts, images, and so forth, are all files. Input and output devices, and generally all devices, are considered to be files, according to the system.
This lets users treat a variety of entities with a uniform set of operations, even through the implementation of those operations may be wildly different.
As you were getting at with your question, device files are the user facing side of the abstraction. This is what the user sees; a file that they can write to, read from, open, close, etc. The device drivers are the implementation of those operations.
So the user will make a call to a file operation such as write, and then the kernel will then use the device driver to carry out the operation.
Device File like /dev/spidevX.Y is a SW abstraction of a SPI device which exposes Linux low level SPI API to the userspace with syscalls (in Linux driver world known as "file operations"):
That is read(), write(), ioctl()...
spidev.c is a special kind of driver which is registered for generic SPI client(chip) devices, and it's main goal is to export Kernel low level SPI API to userspace.
There is a whole Linux SPI layer in between defined in spi.c
Device driver representing real HW SPI controller is where callbacks (hooks) are implemented and registered to the kernel as a part of spi_master (spi_controller)structure.
Here is a callback initialization for SPI message transfer:
master->transfer_one_message = atmel_spi_transfer_one_message;
everything in linux is a file.
device driver is a software used by operating system to communicate with device.
device driver makes use of device files.

How do user-space programs interact with a USB 802.11 Wi-Fi driver on Linux?

Allow me to qualify this question by stating that I am new to driver development. I am trying to understand the driver source code for a USB Wi-Fi card that uses a RealTek 8187L chip. Based on a good answer to my previous question, I established that the relevant driver source code that I needed to inspect is in drivers/net/wireless/rtl818x/rtl8187/dev.c (inside the Linux kernel source).
Doing some reading, it seems as though a USB driver instantiates a usb_driver struct that it registers with the kernel, which describes (among other things) the devices the driver supports (.id_table), the function to execute when a supported device is connected (.probe) and optionally, a set of file operations (.fops), for interaction with user-space. The usb_driver struct associated with the 8187L driver does not include a .fops:
static struct usb_driver rtl8187_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl8187_table,
.probe = rtl8187_probe,
.disconnect = __devexit_p(rtl8187_disconnect),
.disable_hub_initiated_lpm = 1,
};
module_usb_driver(rtl8187_driver);
Hence, I am curious as to how user-space programs are interacting with this driver to send and receive data.
On an old Linux Journal post (2001), there is the following excerpt:
The fops and minor variables are optional. Most USB drivers hook into another kernel
subsystem, such as the SCSI, network or TTY subsystem. These types of drivers register
themselves with the other kernel subsystem, and any user-space interactions are provided
through that interface. But for drivers that do not have a matching kernel subsystem,
such as MP3 players or scanners, a method of interacting with user space is needed. The
USB subsystem provides a way to register a minor device number and a set of
file_operations [fops] function pointers that enable this user-space interaction.
So it sounds like the 8187L driver is probably one that "hooks into another kernel subsystem". So I suppose my question is, for such a driver, which doesn't supply a .fops function pointer, how is the interaction taking place with this other kernel subsystem? Ultimately I want to be able to find the point(s) in the driver code that programs are actually interacting with to send and receive data so I can continue to analyse how the code works.
The driver for an individual wireless chipset is at a very low level. There are many layers between it and userspace. The next layer above rtl8187 is mac80211. In drivers/net/wireless/rtl818x/rtl8187/dev.c observe the call to ieee80211_register_hw. That registration call provides the link between the mac80211 layer and the rtl8187 device.
Next look at the implementation of ieee80211_register_hw, found in net/mac80211/main.c. That calls ieee80211_if_add, found in net/mac80211/iface.c, which calls register_netdevice. And that puts the device in the kernel's main list of network interfaces, making it available for things like ifconfig and route.
Most userspace programs don't interact directly with a network interface, they just send packets to an IP address and the kernel uses the routing table to choose an outgoing interface.
The RTL8187 driver registers itself with the IEEE 802.11 wireless networking subsystem, by calling ieee80211_alloc_hw() and ieee80211_register_hw() in its probe function.

How to access i2c device driver node

Situation 1:
I have an i2c chip driver as part of linux kernel. I can verify the i2c chip driver is in the kernel from kernel boot messages (my chip driver is mma8450)
dmesg:
mma8450 0-001c: uevent
I can also see this driver in (0x1c is i2c address of chip)
cat /sys/bus/i2c/devices/0-001c/name
mma8450
I can not see this driver node in /dev interface. My question is how can I create node of this device in /dev so that I can access this device in a user program ?
Situation 2:
I create the module of the same chip driver and does not make it a part of kernel. I can load this module using insmod mma8450, how can I create a node of this device as I don't have its major / minor numbers ? (I can not see major & minor numbers assigned to this driver in mma8450 source code)
Any help is appreciated
Regards
Load the kernel module:
modprobe i2c-dev
ls /dev/i2*
/dev/i2c-0
/dev/i2c-10
/dev/i2c-12
/dev/i2c-14
/dev/i2c-3
/dev/i2c-5
/dev/i2c-7
/dev/i2c-9
/dev/i2c-1
/dev/i2c-11
/dev/i2c-13
/dev/i2c-2
/dev/i2c-4
/dev/i2c-6
/dev/i2c-8
Find the major/minor numbers for your device:
cat /proc/devices
You should see a device for the i2c bus and one for the i2c device itself.
Create the device node for the i2c device driver:
mknod /dev/[device name] [type] [major] [minor]
This is 3-Axis Accelerometer. Linux registers it as a driver for input_polled_dev type.
You can uaccess it using /dev/i2c-x bus (controller) device node, but there is no much sense using it that way directly from userspace.
I2C clients are not meant to be used using /dev device nodes.
They should be registered to Kernel I2C framework and used through higher layers API.
There is sample program for reading similar MMA7455L x,y,z registers from userspace using /dev/i2c-X bus device node.
Reading the Accelerometer With I²C

Resources