# GPIO, linux kernel module and ioctl ###### tags: `gpio` `kremel module` `ioctl` ## :memo: GPIO pin * `/proc/device-tree` * How to? ```shell= $> cat /proc/device-tree/internal_slot\@1/power_pin_gpio > /tmp/out $> xxd /tmp/out 00000000: 0000 0014 0000 0000 ........ ``` so the gpio pin is `0x14`=`20` * grub configure (*keyword is related to commertial secret) ```shell= $> echo 1 > /proc/sys/kernel/{keyword}_install_flag $> mount -t vfat /dev/{keyword}boot1 /mnt cat /mnt/EFI/boot/{keyword}}BootLoader.conf syno_serial --pci=0,24,2 --speed=115200 --uppci=0,24,0 --upspeed=115200 terminal_input serial terminal_output serial set default='1' set timeout='3' set fallback='0' menuentry "xxx" { search --fs-uuid --no-floppy --set=root 10EE-589C devicetree /model.dtb linux /zImage root=/dev/md0 intel_iommu=igfx_off netif_num=2 HddEnableDynamicPower=1 xxx vender_format_version=2 xxx initrd /rd.gz } ... ``` the `/model.dtb` is the file describing device-tree. reference: [Device Tree Reference](https://elinux.org/Device_Tree_Reference) :::info The primary purpose of Device Tree in Linux is to provide a way to describe non-discoverable hardware. This information was previously hard coded in source code. ::: * `/proc/cmdline` ```shell= $> cat /proc/cmdline ``` reference: [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html) ## :memo: GPIO and kernel module references: 1. [Writing a Linux Kernel Module — Part 3: Buttons and LEDs](http://derekmolloy.ie/kernel-gpio-programming-buttons-and-leds/) 2. [GPIO Interfaces (in Kernel Space)](https://www.kernel.org/doc/Documentation/gpio/gpio.txt) 3. [The GPIO Sysfs Interface for User Space](https://www.kernel.org/doc/Documentation/gpio/sysfs.txt) ### GPIO in linux: `linux/gpio.h` ```clike= static inline int gpio_request(unsigned gpio, const char *label) // allocate the GPIO number, the label is for sysfs static inline int gpio_export(unsigned gpio, bool direction_may_change) // make available via sysfs and decide if it can change from input to output and vice versa static inline int gpio_direction_input(unsigned gpio) // an input line (as usual, return of 0 is success) static inline int gpio_get_value(unsigned gpio) // get the value of the GPIO line static inline int gpio_direction_output(unsigned gpio, int value) // value is the state static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) // set debounce time in ms (platform dependent) static inline int gpio_sysfs_set_active_low(unsigned gpio, int value) // set active low (invert operation states) static inline void gpio_unexport(unsigned gpio) // remove from sysfs static inline void gpio_free(unsigned gpio) // deallocate the GPIO line static inline int gpio_to_irq(unsigned gpio) // associate with an IRQ ``` ### `ioctl` in `linux-4.4.x/Documentation/ioctl/ioctl-number.txt`: :::spoiler If you are adding new ioctl's to the kernel, you should use the _IO macros defined in <linux/ioctl.h>: _IO an ioctl with no parameters _IOW an ioctl with write parameters (copy_from_user) _IOR an ioctl with read parameters (copy_to_user) _IOWR an ioctl with both write and read parameters. 'Write' and 'read' are from the **user's point of view**, just like the system calls 'write' and 'read'. For example, a SET_FOO ioctl would be _IOW, although the kernel would actually read data from user space; a GET_FOO ioctl would be _IOR, although the kernel would actually write data to user space. **The first argument** to _IO, _IOW, _IOR, or _IOWR is an **identifying letter or number from the table below**. Because of the large number of drivers, many drivers share a partial letter with other drivers. If you are writing a driver for a new device and need a letter, **pick an unused block** with enough room for expansion: 32 to 256 ioctl commands. You can register the block by patching this file and submitting the patch to Linus Torvalds. Or you can e-mail me at <mec@shout.net> and I'll register one for you. **The second argument** to _IO, _IOW, _IOR, or _IOWR is a sequence number to **distinguish ioctls from each other**. **The third argument** to _IOW, _IOR, or _IOWR is the type of the data going into the kernel or coming out of the kernel (e.g. 'int' or 'struct foo'). NOTE! Do NOT use sizeof(arg) as the third argument as this results in your ioctl thinking it passes an argument of type size_t. Some devices use their major number as the identifier; this is OK, as long as it is unique. Some devices are irregular and don't follow any convention at all. ::: references: 1. [基礎 Linux Device Driver 驅動程式#9 (IOCTL)](http://csw-dawn.blogspot.com/2012/01/linux-device-driver-9-ioctl.html) 2. [General Purpose Input/Output (GPIO)](https://www.kernel.org/doc/html/latest/driver-api/gpio/index.html) 3. [Linux GPIO Driver Guide](http://shyuanliang.blogspot.com/2012/08/linux-gpio-driver-guide.html) 4. [Writing a Linux Kernel Module — Part 3: Buttons and LEDs](http://derekmolloy.ie/kernel-gpio-programming-buttons-and-leds/) 5. [GPIO Sysfs Interface for Userspace](https://www.kernel.org/doc/Documentation/gpio/sysfs.txt)