Main / Drivers
Linux DevicesHow the Linux system sees drivers... e.g. every USB device is driven by a USB module that works with the USB subsystem, but the device itself shows up in the system as a char device (a USB serial port, say), a block device (a USB memory card reader), or a network device (a USB Ethernet interface). A key difference between character and block devices is that character devices can't use seek and don't have a concept of size. MTD is a new-ish type of device that is a translation of a block device. proccat /proc/devices gives you a list of the drivers present, with major numbers on the left side. The kernel exports information about open network sockets. The relevant /proc/net/ files for IPv4 are: tcp, udp, and raw (are these the "types" of sockets?). A process' open sockets are listed under /proc/[pid]/fd/. What if /proc/modules is empty and lsmod returns nothing?This means the kernel modules are compiled in directly and support for inserting modules may be disabled. sysfs/sys/class is a kernel IF similar to /proc; when you read data from procfs or sysfs, it's really an info request from kernel - data is formatted and returned. The /sys/class entries are created at startup when subsystems register with kobject core. They then begin to discover objects. A device class describes a functional type of device. No 1:1 mapping of class objects and physical devices, as each device may have multiple objects to perform different functions. There may be exposed parameters to control or describe the class object. Both sysfs and procfs are RAM file systems. If you do an ls on /sys/class, you get a list of device types. For USB devices, these seem to match "subsystem" names. ls /sys/class/ bdi gpio mdio_bus net regulator scsi_host vc block i2c-adapter mem pps rtc sound vtconsole bsg i2c-dev misc ptp scsi_device spi_master watchdog dma input mmc_host pwm scsi_disk tty For PWM For the Boundary Devices kernel build for the Nitrogen, you are looking at /sys/class/backlight/pwm-backlight.0/ or /sys/class/backlight/backlight-<id>/ Latency discussion: “Accessing procfs or sysfs files does not entail an I/O bottleneck because they are not real files -- they are kernel interfaces. So no, accessing this stuff through "the file layer" does not affect performance. This is a not uncommon misconception in linux systems programming, I think. Programmers can be squeamish about system calls that aren't well, system calls, and paranoid that opening a file will be somehow slower. Of course, file I/O in the ABI is just system calls anyway. What makes a normal (disk) file read slow is not the calls to open, read, write, whatever, it's the hardware bottleneck.” http://stackoverflow.com/questions/19554154/in-general-on-uclinux-is-ioctl-faster-than-writing-to-sys-filesystem Adding a sysfs attributehttps://lwn.net/Articles/54651/ You create a bin_attribute struct which contains name and permissions and handles to read and write functions, and then use the sysfs _create_ and _remove_ functions in driver setup and pull down. udev and libudevGreat walkthrough of sysfs and udev here: http://cholla.mmto.org/computers/usb/OLD/tutorial_usbloger.html and intro to udevadm here: https://www.tecmint.com/udev-for-device-detection-management-in-linux/ http://wiki.gentoo.org/wiki/Udev Obsoleted at some point (at least by 2020 and Ubuntu 20) by libsystemd and sd-device. Note that older versions of libudev (pre-2012/2013?) had a blocking version of udev_monitor_receive_device() so this required using select() to check a FD for data before using it, but this didn't really work for devices just connecting only and not xmitting. They later changed the function to non-blocking. Older versions of libudev also suffered from memory leaks, although it's not clear where exactly this occurred nor when it/if was fixed. This was seen by me using kernel 3.14 and attempting to use the monitor and devnode path finding tools. To set up new udev rules for something like sending signals to a running application, here is a good note on the difference between /etc/udev/rules.d/ and /lib/udev/rules.d/ (use the former). https://unix.stackexchange.com/questions/333697/etc-udev-rules-d-vs-lib-udev-rules-d-which-to-use-and-why Kernel 2.6.31+ net driver updateIn kernel 2.6.31 the function pointers to net_device operations disappeared from the net_device structure, and were put into a new net_device_ops structure which is a const member of the new copy of net_device. To update, add a kernel version conditional net_device_ops struct, e.g. static const struct net_device_ops foobar_ops = { .ndo_init = 0, .ndo_uninit = 0, .ndo_open = foobar_open, .ndo_stop = foobar_close, .ndo_start_xmit = foobar_xmit, .ndo_set_multicast_list = 0, .ndo_set_mac_address = 0, .ndo_do_ioctl = foobar_ioctl, .ndo_change_mtu = 0, .ndo_get_stats = foobar_get_stats, .ndo_tx_timeout = 0, }; The dev-> function pointer assignments from __init net_init can then be removed. Tell me about IOCTLioctl is one of the standard driver file operations, along with read/write, etc. An ioctl allows you to extend the capabilities of the driver with driver specific operations. What is SIOCDEVPRIVATE?This is the first of 16 ioctl commands that can be implemented by each driver for its own private use. All the network ioctl commands are defined in sockios.h. (From O'Reilly) Note that there was a change in the file operations struct somewhere between kernel 2.6.x and 3.0.x, now you must distinguish between i.e. when filling out your _ioctl function, these can be referenced as offsets from the original: #define FOO_IOCTL_ROCK SIOCDEVPRIVATE + 1 #define FOO_IOCTL_ROLL SIOCDEVPRIVATE + 2 What should my _ioctl look like?//this code lives in the driver //don't forget the .ioctl = foobar_ioctl in the operations struct static int foobar_ioctl(struct net_device* netdev, struct ifreq __user* ifr, int cmd ) { MY_DATA_TYPE* foobar_priv; immap_t* immap; foobar_priv = (MY_DATA_TYPE*) netdev_priv(netdev); immap = (immap_t*)foobar_priv->some_kernel_space_guy; switch (cmd) { case FOO_IOCTL_ROCK: printk( KERN_ERR "%s: rock \n", netdev->name); //do some rock stuff break; case FOO_IOCTL_ROLL: printk( KERN_ERR "%s: roll %s\n", netdev->name); //do some roll stuff break; default: break; } return 0; } This function can be called from your user space application when you've included General notesAdding 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. Access registers or any physical mem through /dev/mem. The /dev/mem and /dev/kmem character special files provide access to a pseudo device driver that allows read and write access to system memory or I/O address space. Typically, these special files are used by operating system utilities and commands (such as sar, iostat, and vmstat) to obtain status and statistical information about the system. Basically, on embedded systems most of the drivers will not be built as modules, instead they are statically built into the kernel. To get to know all the drivers, you need to go through the /sys directory. To enable dev_dbg messages in a specific kernel file: #define DEBUG before including <linux/device.h> Platform devices cannot be detected dynamically, so they are statically defined: Notes on some output files and flags for kernel module compiles: Refresher for kernel modules vs. user programs: Power ManagementThe Linux .config file has CONFIG_SUSPEND and CONFIG_PM parameters but the control for these is fuzzy or nonexistent in some instances. In the defconfig, you can turn off CONFIG_PM_RUNTIME but what this accomplishes is questionable, if anything at all. Some of this stuff may be designed to be inaccessible to the kernel builder for some reason. Kernel ModulesPrimer on kernel modules and user spacehttp://docs.oracle.com/cd/E19120-01/open.solaris/819-3159/emjjr/index.html Building a kernel moduleIf the Makefile is as simple as obj-m += hello.o you can build with make hello.o But, if you need to link to the kernel for system functions, you'll need the extras that add make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules You need to use the same gcc compiler version for your module that was used to compile the kernel itself on the system on which you'll be running your module. You can find out which version with cat /proc/version. KM programming guides: http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN323 http://derekmolloy.ie/writing-a-linux-kernel-module-part-1-introduction/ To search for a module that may be statically built into the kernel instead of loadable: grep <module-name> /lib/modules/`uname -r`/modules.builtin ARM ioremaphttp://www.crashcourse.ca/wiki/index.php/Ioremap_and_friends NAND flash stuff meant for the flash pagehttp://free-electrons.com/blog/managing-flash-storage-with-linux/ GPIOGPIO interaction is possible using the /sys/class/gpio interface. To give access, you are supposed to be able to echo the number of the desired gpio port to export. This is supposed to create a gpioX listing to use. What a PowerPC SPI device driver might look like#include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_INFO */ #include <linux/init.h> /* Needed for the macros */ #include <linux/proc_fs.h> /* Needed for /proc entry */ #include <asm/cpm2.h> /* memory */ #include "myfoo.h" // map immr and parameter ram /* SPI Controller mode register definitions /* SPIE register values */ /* SPIM register values */ /* SPCOM start bit */ /* BIT MASKS */ //function decs // essential values to initialize /* RX and TX buffers */ // parameter RAM here int spi_init(void) int spi_exit(void) int spi_rx(unsigned char* buf, unsigned int length) int spi_tx(unsigned char* buf, unsigned int length) static int foo_read_proc( char *page, char **start, off_t off, int count, int *eof, void *data ) static int __init foo_start(void) static void __exit foo_end(void) module_init(foo_start); module_exit(foo_end); Device Register Types
regardless of a change to the high condition. This mode is used in some Ethernet PHY registers.
|