How to associate the device in /dev/ with the actual driver - linux

I am trying to understand how device driver works in linux.
I have a device node as follows (Major number 89, device name i2c-0)
crw-r--r-- 1 0 0 89, 0 Sep 29 01:36 /dev/i2c-0
I have the i2c driver with the name i2c.ko and I will do insmod i2c.ko during start up.
And in the driver , following function will be called during initialization:
register_chrdev(89, "i2c", &i2chtv_fops)<0 // not "i2c-0"
My question is : When user call open("/dev/i2c-0", O_RDWR),how the kernel knows which driver to use ? I noticed the device name is i2c-0 but registered device name is i2c. Is it because they are use the same major number that the kernel can use the correct driver?

The major number tells you which driver handles which device file. The minor number is used only by the driver itself to differentiate which device it's operating on, just in case the driver handles more than one device.
Adding a driver to your system means registering it with the kernel. This is synonymous with assigning it a major number during the module's initialization. You do this by using the register_chrdev function, defined by linux/fs.h.
int register_chrdev(unsigned int major, const char *name,
struct file_operations *fops);
where unsigned int major is the major number you want to request, const char *name is the name of the device as it'll appear in /proc/devices and struct file_operations *fops is a pointer to the file_operations table for your driver. A negative return value means the registertration failed. Note that we didn't pass the minor number to register_chrdev. That's because the kernel doesn't care about the minor number; only our driver uses it.
From here

Yes, major numbers select the driver and minor numbers select "units" (whatever that may be; for the console driver, it's the different screens).
The -0 you see is the "unit" (in case you have more than a single i2c bus in your system).

Related

Getting ENOTTY on ioctl for a Linux Kernel Module

I have the following chardev defined:
.h
#define MAJOR_NUM 245
#define MINOR_NUM 0
#define IOCTL_MY_DEV1 _IOW(MAJOR_NUM, 0, unsigned long)
#define IOCTL_MY_DEV2 _IOW(MAJOR_NUM, 1, unsigned long)
#define IOCTL_MY_DEV3 _IOW(MAJOR_NUM, 2, unsigned long)
module .c
static long device_ioctl(
struct file* file,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
...
}
static int device_open(struct inode* inode, struct file* file)
{
...
}
static int device_release(struct inode* inode, struct file* file)
{
...
}
struct file_operations Fops = {
.open=device_open,
.unlocked_ioctl= device_ioctl,
.release=device_release
};
static int __init my_dev_init(void)
{
register_chrdev(MAJOR_NUM, "MY_DEV", &Fops);
...
}
module_init(my_dev_init);
My user code
ioctl(fd, IOCTL_MY_DEV1, 1);
Always fails with same error: ENOTTY
Inappropriate ioctl for device
I've seen similar questions:
i.e
Linux kernel module - IOCTL usage returns ENOTTY
Linux Kernel Module/IOCTL: inappropriate ioctl for device
But their solutions didn't work for me
ENOTTY is issued by the kernel when your device driver has not registered a ioctl function to be called. I'm afraid your function is not well registered, probably because you have registered it in the .unlocked_ioctl field of the struct file_operations structure.
Probably you'll get a different result if you register it in the locked version of the function. The most probable cause is that the inode is locked for the ioctl call (as it should be, to avoid race conditions with simultaneous read or write operations to the same device)
Sorry, I have no access to the linux source tree for the proper name of the field to use, but for sure you'll be able to find it yourself.
NOTE
I observe that you have used macro _IOW, using the major number as the unique identifier. This is probably not what you want. First parameter for _IOW tries to ensure that ioctl calls get unique identifiers. There's no general way to acquire such identifiers, as this is an interface contract you create between application code and kernel code. So using the major number is bad practice, for two reasons:
Several devices (in linux, at least) can share the same major number (minor allocation in linux kernel allows this) making it possible for a clash between devices' ioctls.
In case you change the major number (you configure a kernel where that number is already allocated) you have to recompile all your user level software to cope with the new device ioctl ids (all of them change if you do this)
_IOW is a macro built a long time ago (long ago from the birth of linux kernel) that tried to solve this problem, by allowing you to select a different character for each driver (but not dependant of other kernel parameters, for the reasons pointed above) for a device having ioctl calls not clashing with another device driver's. The probability of such a clash is low, but when it happens you can lead to an incorrect machine state (you have issued a valid, working ioctl call to the wrong device)
Ancient unix (and early linux) kernels used different chars to build these calls, so, for example, tty driver used 'T' as parameter for the _IO* macros, scsi disks used 'S', etc.
I suggest you to select a random number (not appearing elsewhere in the linux kernel listings) and then use it in all your devices (probably there will be less drivers you write than drivers in the kernel) and select a different ioctl id for each ioctl call. Maintaining a local ioctl file with the registered ioctls this way is far better than trying to guess a value that works always.
Also, a look at the definition of the _IO* macros should be very illustrative :)

How to get a device file name using major and minor number

I am trying add some debug messages in block io to track the io operation in linux kernel.
IO could happen to multiple block device, I have dev_t value with me.
I can get major and minor number from dev_t.
I want to know is there any way to get the device file name from /dev/ dir using these major and minor number?
Of course, I need kernel APIs.
It's simple:
Use bdget function to find the block_device by dev_t.
Use bdevname to get the device name.
Use bdput to put the device reference.
Have fun.
You can also use libudev. Since you already have the dev_t id this way is aesier.
#include <libudev.h>
// Create the udev context.
struct udev *udev = udev_new();
// Create de udev_device from the dev_t.
struct udev_device *dev = udev_device_new_from_devnum(udev, 'b', sb.st_dev);
// Finally obtain the node.
const char* node = udev_device_get_devnode(dev);
udev_unref(udev);
In general, you cannot do such simple reverse mapping. This is because knowing some major and major numbers, one can always use mknod to create valid device file anywhere, not necessarily under /dev.
At the end of the day, kernel does not care much how did any particular device node with certain major/minor came about - such a node is simply entry point into the kernel device driver that can handle this hardware or software device.
Granted, in practice on most modern Linux systems most device nodes are located in /dev and maintained by udev - but it is user-space daemon, which your kernel driver cannot talk to. Also note that udev can be configured to create new device nodes with any name.

linux gpio c api

I have an powerpc board with 3.2 kernel running on it. Accessing gpio with sysfs works as expected e.g.
> echo 242 > /sys/class/gpio/export
> cat /sys/class/gpio/gpio242/value
> 1
Is there no API to direct access gpio pins from user space? Must I deal with the text based sysfs interface?
I seach for something like:
gpio_set(int no, int val);
Thanks
Klaus
GPIO access through sysfs has been deprecated since Linux 4.8.
The new way for user space access is through libgpiod, which includes a library to link with (obviously), as well as some tools which can be run from the command line (for scripting convenience). Notably, GPIO lines are referenced with the line name string rather than an integer identifier, like with sysfs. E.g.
gpioset $(gpiofind "USR-LED-2")=1
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/README
Edit: sysfs direct access for GPIOs is deprecated, new way is programmatic through libgpiod
sysfs is the lowest level at which you will be able to manipulate GPIO in recent kernels. It can be a bit tedious but it offers several advantages over the old style API:
No ugly ioctl
Can be scripted very easily (think startup scripts)
For inputs, the "value" file can easily be poll-ed for rising/falling/both edges and it will be very reactive to hardware interrupts
I have no example code at the moment but when accessing them through C code, I often implemented a very simple wrapper manipulating file descriptors and having variations of the following interface:
int gpio_open(int number, int out); /* returns handle (fd) */
int gpio_close(int gpio);
int gpio_set(int gpio, int up);
int gpio_get(int gpio, int *up);
int gpio_poll(int gpio, int rising_edge, int timeout);
From then, the implementation is pretty straightforward.
Once you have the devices created in the vfs tree, you can open them like typical files assuming you have a driver written and have the correct major and minor numbers assigned in the makedev file that creates the gpio pins on the vfs tree.
Every GPIO is memory mapped as a register, so you can access to it through /dev/mem. See here. If you want to access directly to a GPIO you have to work at kernel space level

Where can I find the IRQ number in request_irq function?

I'm learning device driver programming in Linux. I am wondering where I could find the IRQ number to be used as the "irq" parameter in the request_irq function?
int request_irq (unsigned int irq,
void (*handler) (int, void *, struct pt_regs *),
unsigned long irqflags,
const char *devname,
void *dev_id);
Thanks
You seem learning the device programming from the wrong side - without a device.
If you have e.g. device on PCI but, then its IRQ is negotiated by the PCI and is available via Linux PCI subsystem.
If you have some custom wired device, quite often its IRQ line is hardwired and you should ask the people who made the custom device where it was wired to and what IRQ it is.
Otherwise buy yourself a copy of LDD3 - it's worth it and describes all that in details.
If you have only a single interrupt controller the irq number is simply the hardware IRQ number.
If you have more then one PIC you need to look in the board specific initialization include files to see which offset was given to the specific PIC your device is connected to and add that to the hardware IRQ number.
It is usually an include file named irqs.h in the include/ directory of of the board specific files. E.g. for an Arm based Bcmring board, the file is in linux/arch/arm/mach-bcmring/include/mach/irqs.h

What is the sequence followed by the Linux kernel to configure a device?

As I understood after reading the chapter related to The Linux Device Model in the Linux Device Drivers 3rd Edition, when a new device is configured, the kernel (2.6) follows more or less this sequence:
The Device is registered in the driver core (device_register(), what includes device initialization)
A kobject is registered in the device model
It creates an entry in sysfs and provokes a hotplug event
Bus and drivers are checked to see which one matches with the device
Probe
Device is binded to the driver
My main doubt is, in step 1, when is device_register() called and what fields should already be set in the device struct?
Is it called by the bus to which the device is connected? Any example in the code?
Have I misunderstood anything? :)
PCI hotplug code is going to call pci_do_scan_bus() to go through all slots, see if we find a device/bridge and add them to our device tree :
unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) {
max = pci_scan_child_bus(bus) //scan bus for all slots and devices in them
pci_bus_add_devices(bus); //add what we find
...
}
The fields in struct device are actually filled up as part of call to pci_scan_child_bus(). Here's the call graph (sort of :)):
pci_scan_child_bus > pci_scan_slot (scan for slots on the bus) > pci_scan_single_device > pci_device_add > device_initialize.
Note that device_initialize() is the first part of device_register(). You will see that the fields of struct device are filled up in pci_device_add after the call to device_initialize(). You can find it under drivers/pci/probe.c in the kernel sources. The struct pci_dev will also be filled up which will later be used by the device specific driver.
The actual addition of the kobject to the device hierarchy happens in pci_bus_add_devices. Here's the call graph :
pci_bus_add_devices > pci_bus_add_device > device_add.
As you can see, this call flow completes the second part of the device_register() function.
So, in short, device_register() consists of : 1. Initialize device and 2. Add device.
pci_device_add does step 1 and pci_bus_add_device does step 2.
Files of interest are : drivers/pci/{pci.c,bus.c,probe.c}
In struct bus type there is pointer to function match, whose job is to match the driver associated with device. So when the device is associated with a bus, then as soon as the device is connected to bus then it is responsiblity of bus to search for the device.
Pls correct me if that is not the case.

Resources