# 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)