Try โ€‚โ€‰HackMD

GPIO, linux kernel module and ioctl

tags: gpio kremel module ioctl

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
GPIO pin

  • /proc/device-tree
    • How to?
    โ€‹โ€‹โ€‹โ€‹$> 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)
$> 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

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
$> cat /proc/cmdline

reference: proc(5)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More โ†’
GPIO and kernel module

references:

  1. Writing a Linux Kernel Module โ€” Part 3: Buttons and LEDs
  2. GPIO Interfaces (in Kernel Space)
  3. The GPIO Sysfs Interface for User Space

GPIO in linux: linux/gpio.h

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:

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)
  2. General Purpose Input/Output (GPIO)
  3. Linux GPIO Driver Guide
  4. Writing a Linux Kernel Module โ€” Part 3: Buttons and LEDs
  5. GPIO Sysfs Interface for Userspace