unix: add GPIO constants and structs

This adds everything needed to use Linux's GPIO V2 UAPI, including the
ioctls, structs and constants.
As on some architectures char is signed by default and the UAPI doesn't
make it unsigned explicitly a mkpost fixup is used to make the types
more usable (by things like unix.ByteSliceToString).

Change-Id: Icdb0ca4a225316ca5e948e21ab21789636297a57
Reviewed-on: https://go-review.googlesource.com/c/sys/+/752623
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Tobias Klauser <tobias.klauser@gmail.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
diff --git a/unix/linux/types.go b/unix/linux/types.go
index c6a2b62..426ca29 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -117,6 +117,7 @@
 #include <linux/fs.h>
 #include <linux/fsverity.h>
 #include <linux/genetlink.h>
+#include <linux/gpio.h>
 #include <linux/hdreg.h>
 #include <linux/hidraw.h>
 #include <linux/icmp.h>
@@ -6297,3 +6298,34 @@
 	MPOL_PREFERRED_MANY      = C.MPOL_PREFERRED_MANY
 	MPOL_WEIGHTED_INTERLEAVE = C.MPOL_WEIGHTED_INTERLEAVE
 )
+
+// GPIO API
+const (
+	GPIO_GET_CHIPINFO_IOCTL          = C.GPIO_GET_CHIPINFO_IOCTL
+	GPIO_V2_GET_LINEINFO_IOCTL       = C.GPIO_V2_GET_LINEINFO_IOCTL
+	GPIO_V2_GET_LINE_IOCTL           = C.GPIO_V2_GET_LINE_IOCTL
+	GPIO_V2_LINE_GET_VALUES_IOCTL    = C.GPIO_V2_LINE_GET_VALUES_IOCTL
+	GPIO_V2_LINE_SET_VALUES_IOCTL    = C.GPIO_V2_LINE_SET_VALUES_IOCTL
+	GPIO_V2_GET_LINEINFO_WATCH_IOCTL = C.GPIO_V2_GET_LINEINFO_WATCH_IOCTL
+	GPIO_GET_LINEINFO_UNWATCH_IOCTL  = C.GPIO_GET_LINEINFO_UNWATCH_IOCTL
+)
+const (
+	GPIO_V2_LINE_ATTR_ID_FLAGS         = C.GPIO_V2_LINE_ATTR_ID_FLAGS
+	GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES = C.GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES
+	GPIO_V2_LINE_ATTR_ID_DEBOUNCE      = C.GPIO_V2_LINE_ATTR_ID_DEBOUNCE
+	GPIO_V2_LINE_CHANGED_REQUESTED     = C.GPIO_V2_LINE_CHANGED_REQUESTED
+	GPIO_V2_LINE_CHANGED_RELEASED      = C.GPIO_V2_LINE_CHANGED_RELEASED
+	GPIO_V2_LINE_CHANGED_CONFIG        = C.GPIO_V2_LINE_CHANGED_CONFIG
+	GPIO_V2_LINE_EVENT_RISING_EDGE     = C.GPIO_V2_LINE_EVENT_RISING_EDGE
+	GPIO_V2_LINE_EVENT_FALLING_EDGE    = C.GPIO_V2_LINE_EVENT_FALLING_EDGE
+)
+
+type GPIOChipInfo C.struct_gpiochip_info
+type GPIOV2LineValues C.struct_gpio_v2_line_values
+type GPIOV2LineAttribute C.struct_gpio_v2_line_attribute
+type GPIOV2LineConfigAttribute C.struct_gpio_v2_line_config_attribute
+type GPIOV2LineConfig C.struct_gpio_v2_line_config
+type GPIOV2LineRequest C.struct_gpio_v2_line_request
+type GPIOV2LineInfo C.struct_gpio_v2_line_info
+type GPIOV2LineInfoChanged C.struct_gpio_v2_line_info_changed
+type GPIOV2LineEvent C.struct_gpio_v2_line_event
diff --git a/unix/mkpost.go b/unix/mkpost.go
index 5aa20c6..26ee5d2 100644
--- a/unix/mkpost.go
+++ b/unix/mkpost.go
@@ -194,6 +194,15 @@
 		b = bytes.Replace(b, s, newNames, 1)
 	}
 
+	// Convert []int8 to []byte in GPIO structs
+	convertGPIONames := regexp.MustCompile(`(Name|Label|Consumer)(\s+)\[(\d+)\]u?int8`)
+	gpioTypes := regexp.MustCompile(`type GPIO\S+ struct {[^}]*}`)
+	gpioStructs := gpioTypes.FindAll(b, -1)
+	for _, s := range gpioStructs {
+		newNames := convertGPIONames.ReplaceAll(s, []byte("$1$2[$3]byte"))
+		b = bytes.Replace(b, s, newNames, 1)
+	}
+
 	// Convert []int8 to []byte in ctl_info ioctl interface
 	convertCtlInfoName := regexp.MustCompile(`(Name)(\s+)\[(\d+)\]int8`)
 	ctlInfoType := regexp.MustCompile(`type CtlInfo struct {[^}]*}`)
diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go
index d11d5b9..526a0d5 100644
--- a/unix/ztypes_linux.go
+++ b/unix/ztypes_linux.go
@@ -6397,3 +6397,79 @@
 	MPOL_PREFERRED_MANY      = 0x5
 	MPOL_WEIGHTED_INTERLEAVE = 0x6
 )
+
+const (
+	GPIO_V2_GET_LINEINFO_IOCTL       = 0xc100b405
+	GPIO_V2_GET_LINE_IOCTL           = 0xc250b407
+	GPIO_V2_LINE_GET_VALUES_IOCTL    = 0xc010b40e
+	GPIO_V2_LINE_SET_VALUES_IOCTL    = 0xc010b40f
+	GPIO_V2_GET_LINEINFO_WATCH_IOCTL = 0xc100b406
+	GPIO_GET_LINEINFO_UNWATCH_IOCTL  = 0xc004b40c
+)
+const (
+	GPIO_V2_LINE_ATTR_ID_FLAGS         = 0x1
+	GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES = 0x2
+	GPIO_V2_LINE_ATTR_ID_DEBOUNCE      = 0x3
+	GPIO_V2_LINE_CHANGED_REQUESTED     = 0x1
+	GPIO_V2_LINE_CHANGED_RELEASED      = 0x2
+	GPIO_V2_LINE_CHANGED_CONFIG        = 0x3
+	GPIO_V2_LINE_EVENT_RISING_EDGE     = 0x1
+	GPIO_V2_LINE_EVENT_FALLING_EDGE    = 0x2
+)
+
+type GPIOChipInfo struct {
+	Name  [32]byte
+	Label [32]byte
+	Lines uint32
+}
+type GPIOV2LineValues struct {
+	Bits uint64
+	Mask uint64
+}
+type GPIOV2LineAttribute struct {
+	Id    uint32
+	_     uint32
+	Flags uint64
+}
+type GPIOV2LineConfigAttribute struct {
+	Attr GPIOV2LineAttribute
+	Mask uint64
+}
+type GPIOV2LineConfig struct {
+	Flags     uint64
+	Num_attrs uint32
+	_         [5]uint32
+	Attrs     [10]GPIOV2LineConfigAttribute
+}
+type GPIOV2LineRequest struct {
+	Offsets           [64]uint32
+	Consumer          [32]byte
+	Config            GPIOV2LineConfig
+	Num_lines         uint32
+	Event_buffer_size uint32
+	_                 [5]uint32
+	Fd                int32
+}
+type GPIOV2LineInfo struct {
+	Name      [32]byte
+	Consumer  [32]byte
+	Offset    uint32
+	Num_attrs uint32
+	Flags     uint64
+	Attrs     [10]GPIOV2LineAttribute
+	_         [4]uint32
+}
+type GPIOV2LineInfoChanged struct {
+	Info         GPIOV2LineInfo
+	Timestamp_ns uint64
+	Event_type   uint32
+	_            [5]uint32
+}
+type GPIOV2LineEvent struct {
+	Timestamp_ns uint64
+	Id           uint32
+	Offset       uint32
+	Seqno        uint32
+	Line_seqno   uint32
+	_            [6]uint32
+}
diff --git a/unix/ztypes_linux_386.go b/unix/ztypes_linux_386.go
index 97ef790..aede1de 100644
--- a/unix/ztypes_linux_386.go
+++ b/unix/ztypes_linux_386.go
@@ -711,3 +711,7 @@
 	_          uint32
 	_          uint32
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_amd64.go b/unix/ztypes_linux_amd64.go
index 90b50da..bb3bc4d 100644
--- a/unix/ztypes_linux_amd64.go
+++ b/unix/ztypes_linux_amd64.go
@@ -725,3 +725,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_arm.go b/unix/ztypes_linux_arm.go
index acda136..1fdf4c5 100644
--- a/unix/ztypes_linux_arm.go
+++ b/unix/ztypes_linux_arm.go
@@ -705,3 +705,7 @@
 	_          uint32
 	_          uint32
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_arm64.go b/unix/ztypes_linux_arm64.go
index ef7a99e..063e6f0 100644
--- a/unix/ztypes_linux_arm64.go
+++ b/unix/ztypes_linux_arm64.go
@@ -704,3 +704,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_loong64.go b/unix/ztypes_linux_loong64.go
index 966063d..9cf836c 100644
--- a/unix/ztypes_linux_loong64.go
+++ b/unix/ztypes_linux_loong64.go
@@ -705,3 +705,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_mips.go b/unix/ztypes_linux_mips.go
index dc53b20..1d222fc 100644
--- a/unix/ztypes_linux_mips.go
+++ b/unix/ztypes_linux_mips.go
@@ -710,3 +710,7 @@
 	Ctime_high uint16
 	_          uint16
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_mips64.go b/unix/ztypes_linux_mips64.go
index 9ad0aa8..912cc4a 100644
--- a/unix/ztypes_linux_mips64.go
+++ b/unix/ztypes_linux_mips64.go
@@ -707,3 +707,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_mips64le.go b/unix/ztypes_linux_mips64le.go
index 29d5549..1e358ef 100644
--- a/unix/ztypes_linux_mips64le.go
+++ b/unix/ztypes_linux_mips64le.go
@@ -707,3 +707,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_mipsle.go b/unix/ztypes_linux_mipsle.go
index a4d9e15..df59f32 100644
--- a/unix/ztypes_linux_mipsle.go
+++ b/unix/ztypes_linux_mipsle.go
@@ -710,3 +710,7 @@
 	Ctime_high uint16
 	_          uint16
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_ppc.go b/unix/ztypes_linux_ppc.go
index f8a2977..29355aa 100644
--- a/unix/ztypes_linux_ppc.go
+++ b/unix/ztypes_linux_ppc.go
@@ -718,3 +718,7 @@
 	_          uint32
 	_          [4]byte
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_ppc64.go b/unix/ztypes_linux_ppc64.go
index 4158d6c..c6083a1 100644
--- a/unix/ztypes_linux_ppc64.go
+++ b/unix/ztypes_linux_ppc64.go
@@ -713,3 +713,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_ppc64le.go b/unix/ztypes_linux_ppc64le.go
index 1035af4..6321cc7 100644
--- a/unix/ztypes_linux_ppc64le.go
+++ b/unix/ztypes_linux_ppc64le.go
@@ -713,3 +713,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)
diff --git a/unix/ztypes_linux_riscv64.go b/unix/ztypes_linux_riscv64.go
index 2297125..b44f402 100644
--- a/unix/ztypes_linux_riscv64.go
+++ b/unix/ztypes_linux_riscv64.go
@@ -792,3 +792,7 @@
 	RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE  = 0x6
 	RISCV_HWPROBE_WHICH_CPUS             = 0x1
 )
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_s390x.go b/unix/ztypes_linux_s390x.go
index 8481e9b..b22c795 100644
--- a/unix/ztypes_linux_s390x.go
+++ b/unix/ztypes_linux_s390x.go
@@ -727,3 +727,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x8044b401
+)
diff --git a/unix/ztypes_linux_sparc64.go b/unix/ztypes_linux_sparc64.go
index a6828a0..0b18075 100644
--- a/unix/ztypes_linux_sparc64.go
+++ b/unix/ztypes_linux_sparc64.go
@@ -708,3 +708,7 @@
 	_      uint64
 	_      uint64
 }
+
+const (
+	GPIO_GET_CHIPINFO_IOCTL = 0x4044b401
+)