github.com/holoplot/go-evdev@v0.0.0-20220721205823-d31c64b9d636/ioctl.go (about) 1 package evdev 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "syscall" 8 "unsafe" 9 ) 10 11 const ( 12 ioctlDirNone = 0x0 13 ioctlDirWrite = 0x1 14 ioctlDirRead = 0x2 15 ) 16 17 func trimNull(s string) string { 18 return strings.Trim(s, "\x00") 19 } 20 21 func ioctlMakeCode(dir, typ, nr int, size uintptr) uint32 { 22 var code uint32 23 if dir > ioctlDirWrite|ioctlDirRead { 24 panic(fmt.Errorf("invalid ioctl dir value: %d", dir)) 25 } 26 27 if size > 1<<14 { 28 panic(fmt.Errorf("invalid ioctl size value: %d", size)) 29 } 30 31 code |= uint32(dir) << 30 32 code |= uint32(size) << 16 33 code |= uint32(typ) << 8 34 code |= uint32(nr) 35 36 return code 37 } 38 39 func doIoctl(fd uintptr, code uint32, ptr unsafe.Pointer) error { 40 _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(code), uintptr(ptr)) 41 if errno != 0 { 42 return errors.New(errno.Error()) 43 } 44 45 return nil 46 } 47 48 func ioctlEVIOCGVERSION(fd uintptr) (int32, error) { 49 version := int32(0) 50 code := ioctlMakeCode(ioctlDirRead, 'E', 0x01, unsafe.Sizeof(version)) 51 err := doIoctl(fd, code, unsafe.Pointer(&version)) 52 return version, err 53 } 54 55 func ioctlEVIOCGID(fd uintptr) (InputID, error) { 56 id := InputID{} 57 code := ioctlMakeCode(ioctlDirRead, 'E', 0x02, unsafe.Sizeof(id)) 58 err := doIoctl(fd, code, unsafe.Pointer(&id)) 59 return id, err 60 } 61 62 func ioctlEVIOCGREP(fd uintptr) ([2]uint32, error) { 63 rep := [2]uint32{} 64 code := ioctlMakeCode(ioctlDirRead, 'E', 0x03, unsafe.Sizeof(rep)) 65 err := doIoctl(fd, code, unsafe.Pointer(&rep)) 66 return rep, err 67 } 68 69 func ioctlEVIOCSREP(fd uintptr, rep [2]uint32) error { 70 code := ioctlMakeCode(ioctlDirWrite, 'E', 0x03, unsafe.Sizeof(rep)) 71 return doIoctl(fd, code, unsafe.Pointer(&rep)) 72 } 73 74 func ioctlEVIOCGKEYCODE(fd uintptr) (InputKeymapEntry, error) { 75 entry := InputKeymapEntry{} 76 code := ioctlMakeCode(ioctlDirRead, 'E', 0x04, unsafe.Sizeof(entry)) 77 err := doIoctl(fd, code, unsafe.Pointer(&entry)) 78 return entry, err 79 } 80 81 func ioctlEVIOCSKEYCODE(fd uintptr, entry InputKeymapEntry) error { 82 code := ioctlMakeCode(ioctlDirWrite, 'E', 0x04, unsafe.Sizeof(entry)) 83 return doIoctl(fd, code, unsafe.Pointer(&entry)) 84 } 85 86 func ioctlEVIOCGNAME(fd uintptr) (string, error) { 87 str := [256]byte{} 88 code := ioctlMakeCode(ioctlDirRead, 'E', 0x06, unsafe.Sizeof(str)) 89 err := doIoctl(fd, code, unsafe.Pointer(&str)) 90 return trimNull(string(str[:])), err 91 } 92 93 func ioctlEVIOCGPHYS(fd uintptr) (string, error) { 94 str := [256]byte{} 95 code := ioctlMakeCode(ioctlDirRead, 'E', 0x07, unsafe.Sizeof(str)) 96 err := doIoctl(fd, code, unsafe.Pointer(&str)) 97 return trimNull(string(str[:])), err 98 } 99 100 func ioctlEVIOCGUNIQ(fd uintptr) (string, error) { 101 str := [256]byte{} 102 code := ioctlMakeCode(ioctlDirRead, 'E', 0x08, unsafe.Sizeof(str)) 103 err := doIoctl(fd, code, unsafe.Pointer(&str)) 104 return trimNull(string(str[:])), err 105 } 106 107 func ioctlEVIOCGPROP(fd uintptr) ([]byte, error) { 108 bits := [256]byte{} 109 code := ioctlMakeCode(ioctlDirRead, 'E', 0x09, unsafe.Sizeof(bits)) 110 err := doIoctl(fd, code, unsafe.Pointer(&bits)) 111 return bits[:], err 112 } 113 114 func ioctlEVIOCGKEY(fd uintptr) ([]byte, error) { 115 bits := [KEY_MAX]byte{} 116 code := ioctlMakeCode(ioctlDirRead, 'E', 0x18, unsafe.Sizeof(bits)) 117 err := doIoctl(fd, code, unsafe.Pointer(&bits)) 118 return bits[:], err 119 } 120 121 func ioctlEVIOCGLED(fd uintptr) ([]byte, error) { 122 bits := [LED_MAX]byte{} 123 code := ioctlMakeCode(ioctlDirRead, 'E', 0x19, unsafe.Sizeof(bits)) 124 err := doIoctl(fd, code, unsafe.Pointer(&bits)) 125 return bits[:], err 126 } 127 128 func ioctlEVIOCGSND(fd uintptr) ([]byte, error) { 129 bits := [SND_MAX]byte{} 130 code := ioctlMakeCode(ioctlDirRead, 'E', 0x1a, unsafe.Sizeof(bits)) 131 err := doIoctl(fd, code, unsafe.Pointer(&bits)) 132 return bits[:], err 133 } 134 135 func ioctlEVIOCGSW(fd uintptr) ([]byte, error) { 136 bits := [SW_MAX]byte{} 137 code := ioctlMakeCode(ioctlDirRead, 'E', 0x1b, unsafe.Sizeof(bits)) 138 err := doIoctl(fd, code, unsafe.Pointer(&bits)) 139 return bits[:], err 140 } 141 142 func ioctlEVIOCGBIT(fd uintptr, evtype int) ([]byte, error) { 143 var cnt int 144 145 switch evtype { 146 case 0: 147 // special case, indicating the list of all feature types supported should be returned, 148 // rather than the list of particular features for that type 149 cnt = EV_CNT 150 case EV_KEY: 151 cnt = KEY_CNT 152 case EV_REL: 153 cnt = REL_CNT 154 case EV_ABS: 155 cnt = ABS_CNT 156 case EV_MSC: 157 cnt = MSC_CNT 158 case EV_SW: 159 cnt = SW_CNT 160 case EV_LED: 161 cnt = LED_CNT 162 case EV_SND: 163 cnt = SND_CNT 164 case EV_REP: 165 cnt = REP_CNT 166 case EV_FF: 167 cnt = FF_CNT 168 default: // EV_PWR, EV_FF_STATUS ?? 169 cnt = KEY_MAX 170 } 171 172 bytesNumber := (cnt + 7) / 8 173 174 bits := [KEY_MAX]byte{} 175 code := ioctlMakeCode(ioctlDirRead, 'E', 0x20+evtype, unsafe.Sizeof(bits)) 176 err := doIoctl(fd, code, unsafe.Pointer(&bits)) 177 return bits[:bytesNumber], err 178 } 179 180 func ioctlEVIOCGABS(fd uintptr, abs int) (AbsInfo, error) { 181 info := AbsInfo{} 182 code := ioctlMakeCode(ioctlDirRead, 'E', 0x40+abs, unsafe.Sizeof(info)) 183 err := doIoctl(fd, code, unsafe.Pointer(&info)) 184 return info, err 185 } 186 187 func ioctlEVIOCSABS(fd uintptr, abs int, info AbsInfo) error { 188 code := ioctlMakeCode(ioctlDirWrite, 'E', 0xc0+abs, unsafe.Sizeof(info)) 189 return doIoctl(fd, code, unsafe.Pointer(&info)) 190 } 191 192 func ioctlEVIOCGRAB(fd uintptr, p int32) error { 193 code := ioctlMakeCode(ioctlDirWrite, 'E', 0x90, unsafe.Sizeof(p)) 194 if p != 0 { 195 return doIoctl(fd, code, unsafe.Pointer(&p)) 196 } 197 return doIoctl(fd, code, nil) 198 } 199 200 func ioctlEVIOCREVOKE(fd uintptr) error { 201 var p int32 202 code := ioctlMakeCode(ioctlDirWrite, 'E', 0x91, unsafe.Sizeof(p)) 203 return doIoctl(fd, code, nil) 204 } 205 206 func ioctlUISETEVBIT(fd uintptr, ev uintptr) error { 207 var p int32 208 code := ioctlMakeCode(ioctlDirWrite, 'U', 100, unsafe.Sizeof(p)) 209 return doIoctl(fd, code, unsafe.Pointer(ev)) 210 } 211 212 func ioctlUISETKEYBIT(fd uintptr, key uintptr) error { 213 var p int32 214 code := ioctlMakeCode(ioctlDirWrite, 'U', 101, unsafe.Sizeof(p)) 215 return doIoctl(fd, code, unsafe.Pointer(key)) 216 } 217 218 func ioctlUISETRELBIT(fd uintptr, rel uintptr) error { 219 var p int32 220 code := ioctlMakeCode(ioctlDirWrite, 'U', 102, unsafe.Sizeof(p)) 221 return doIoctl(fd, code, unsafe.Pointer(rel)) 222 } 223 224 func ioctlUISETABSBIT(fd uintptr, abs uintptr) error { 225 var p int32 226 code := ioctlMakeCode(ioctlDirWrite, 'U', 103, unsafe.Sizeof(p)) 227 return doIoctl(fd, code, unsafe.Pointer(abs)) 228 } 229 230 func ioctlUISETMSCBIT(fd uintptr, msc uintptr) error { 231 var p int32 232 code := ioctlMakeCode(ioctlDirWrite, 'U', 104, unsafe.Sizeof(p)) 233 return doIoctl(fd, code, unsafe.Pointer(msc)) 234 } 235 236 func ioctlUISETLEDBIT(fd uintptr, led uintptr) error { 237 var p int32 238 code := ioctlMakeCode(ioctlDirWrite, 'U', 105, unsafe.Sizeof(p)) 239 return doIoctl(fd, code, unsafe.Pointer(led)) 240 } 241 242 func ioctlUISETSNDBIT(fd uintptr, snd uintptr) error { 243 var p int32 244 code := ioctlMakeCode(ioctlDirWrite, 'U', 106, unsafe.Sizeof(p)) 245 return doIoctl(fd, code, unsafe.Pointer(snd)) 246 } 247 248 func ioctlUISETFFBIT(fd uintptr, fe uintptr) error { 249 var p int32 250 code := ioctlMakeCode(ioctlDirWrite, 'U', 107, unsafe.Sizeof(p)) 251 return doIoctl(fd, code, unsafe.Pointer(fe)) 252 } 253 254 func ioctlUISETSWBIT(fd uintptr, sw uintptr) error { 255 var p int32 256 code := ioctlMakeCode(ioctlDirWrite, 'U', 109, unsafe.Sizeof(p)) 257 return doIoctl(fd, code, unsafe.Pointer(sw)) 258 } 259 260 func ioctlUISETPROPBIT(fd uintptr, prop uintptr) error { 261 var p int32 262 code := ioctlMakeCode(ioctlDirWrite, 'U', 110, unsafe.Sizeof(p)) 263 return doIoctl(fd, code, unsafe.Pointer(prop)) 264 } 265 266 func ioctlUIDEVCREATE(fd uintptr) error { 267 code := ioctlMakeCode(ioctlDirNone, 'U', 1, 0) 268 return doIoctl(fd, code, nil) 269 } 270 271 func ioctlUIDEVDESTROY(fd uintptr) error { 272 code := ioctlMakeCode(ioctlDirNone, 'U', 2, 0) 273 return doIoctl(fd, code, nil) 274 }