owned this note
owned this note
Published
Linked with GitHub
Linux Device Driver
====
###### tags: `Linux Kernel`
# Learning Source
==[Linux 2020 link note book](https://docs.google.com/spreadsheets/d/1T2q62OluzjQKeA9A3FvrmsF0a3qj8JSWFN0AixrLH1g/edit#gid=1566290738)==
- [Linux Kernel Module programming Guide by Peter Jay](https://tldp.org/LDP/lkmpg/2.6/lkmpg.pdf)
### Tutorial
- **[Writing a Linux Kernel Module](http://derekmolloy.ie/writing-a-linux-kernel-module-part-1-introduction/)**
- [Embedded Linux kernel and driver development training](https://bootlin.com/training/kernel/)
- [Slide](https://bootlin.com/doc/training/linux-kernel/linux-kernel-slides.pdf), [Practical Labs](https://bootlin.com/doc/training/linux-kernel/linux-kernel-labs.pdf)
- [Linux Kernel Teaching Lab](https://linux-kernel-labs.github.io/master/)
- [Linux Device Drivers, Third Edition](https://lwn.net/Kernel/LDD3/)
- [Troubleshooting Linux Kernel Modules And Device Drivers](https://www.slideshare.net/satpalparmar/troubleshooting-linux-kernel-modules-and-device-drivers-presentation)
### CSE 438/598 Embedded Systems Programming
- [Linux Embedded System programming](http://rts.lab.asu.edu/web_438_Fall_2014/CSE438_Fall2014_Main_page.htm)
- [Summer Short Course on Embedded Systems Programming](http://rts.lab.asu.edu/web_ESP_Summer2014/ESP_Main_page.htm)
# Linux Kernel Device Model Recap
- [The Linux kernel device model pdf](https://events19.linuxfoundation.org/wp-content/uploads/2017/12/Introduction-to-Linux-Kernel-Driver-Programming-Michael-Opdenacker-Bootlin-.pdf)
- ![](https://i.imgur.com/RJZHWW4.png)
## Driver is between bus infrastructure and framework.
## Device Model Key Data Structures
1. `struct bus_type`
2. `struct device_driver`
3. `struct device`
## Device Model
- ==Adapter driver==: USB controllers, PCI controllers
- The USB adapter driver that corresponds to the USB controller registers itself to the USB core.
- `usb_add_hcd`
- e.g.: linux/drivers/pci/controller/dwc/pcie-designware-plat.c
- `builtin_platform_driver(dw_plat_pcie_driver);`
- ==Device Driver==: USB device driver
- The rtl8150 USB device driver registers itself to the USB core
- `usb_register()`: register the driver structure
- `struct usb_driver`: hooking function `device_driver`
- `struct usb_device_id`: register supported devices
- ==Bus infrastructure==: Bus core (USB core, PCI core)
- The USB core now knows the association between the vendor/product IDs of rtl8150 and the `struct usb_driver` structure of this driver.
![](https://i.imgur.com/4tPO1mY.png)
:::info
### Register the Device Driver flow
- `driver_register`: register driver with bus
- `driver_find`: locate driver on a bus by its name.
- `bus_add_driver`: Add a driver to the bus
driver_attach => bus_for_each_dev => __driver_attach
=> async_schedule_dev => __driver_attach_async_helper
=> driver_probe_device => really_probe => *drv->probe*
- `driver_add_groups`: Add sysfs file for driver
:::
## When a device detected
![](https://i.imgur.com/GDtkcJ1.png)
## The adpater Driver is device driver,too
![](https://i.imgur.com/wrc53QJ.png)
## Platform Device and Drivers
### Describing non-detectable devices
- Use [Device Tree](https://bootlin.com/pub/conferences/2014/elc/petazzoni-device-tree-dummies/petazzoni-device-tree-dummies.pdf)
- All Device Tree bindings in kernel: Documentation/devicetree/bindings
- Dump the DTB file:
```
sudo apt-get install dtc
dtc -I dtb -o dts user-bbb.dtb>user-bbb.dts
```
## e.g. I2C driver (Adapter Driver)
- Matching by name (mandatory for I2C)
- Matching by compatible property (for DT)
- Matching by ACPI ID (for ACPI systems - x86)
```clike=
static const struct i2c_device_id mma7660_i2c_id[] = {
{"mma7660", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id);
static const struct of_device_id mma7660_of_match[] = {
{ .compatible = "fsl,mma7660" },
{ }
};
MODULE_DEVICE_TABLE(of, mma7660_of_match);
static const struct acpi_device_id mma7660_acpi_id[] = {
{"MMA7660", 0},
{}
};
```
- `mma7660_probe`: Register to bus framework.
- `mma7660_remove`: Unregister from bus framework
```clike
static struct i2c_driver mma7660_driver = {
.driver = {
.name = "mma7660",
.pm = MMA7660_PM_OPS,
.of_match_table = mma7660_of_match,
.acpi_match_table = ACPI_PTR(mma7660_acpi_id),
},
.probe = mma7660_probe,
.remove = mma7660_remove,
.id_table = mma7660_i2c_id,
};
module_i2c_driver(mma7660_driver);
```
# 其它單元傳送門
- [Linux 核心模組掛載機制](https://hackmd.io/@sysprog/linux2020-fibdrv#-Linux-%E6%A0%B8%E5%BF%83%E6%A8%A1%E7%B5%84%E6%8E%9B%E8%BC%89%E6%A9%9F%E5%88%B6)
- [Character Drivers 101](/4mvdsQJ4QJyCb6AQ2RZ0_Q?sync=&type=)
- [Linux Virtual File System](https://hackmd.io/LHkzTBMGRQisGc9syR_ZGw?view#Linux-Virtual-File-System)
# Building External Modules
- How to write the kernel module makefile:
`Documentation/kbuild/modules.rst`
- Further documentation describing the syntax used by kbuild is
located in `Documentation/kbuild/makefiles.rst`.
- [Building External Modules](https://www.kernel.org/doc/Documentation/kbuild/modules.rst)
```
obj-m := <module_name>.o
```
Result in the kernel module `<module_name>.ko`
When the module is built from multiple sources, an additional line is
needed listing the files:
```
<module_name>-y := <src1>.o <src2>.o ...
```
or
```cmake
<module_name>-objs := ./<src1>.o \
./<src1>.o
```
# Linux GPIO Driver
- GPIO driver (user-level interface) : ./driver/gpio/gpiolib.c
# MMAP Access kernel Space
[PFN Method: Github](https://github.com/dkarnikis/linux-kernel-code/blob/master/mmap_device_driver/mmap_device_driver/mmap_device.c)
[My Code Example](https://github.com/ldotrg/practical_coding/tree/master/kernel_module/char_mmap)
[LDD3 MMAP and DMA](https://static.lwn.net/images/pdf/LDD3/ch15.pdf)