├── .gitignore ├── LICENSE ├── README.md ├── bitmap.go ├── bitmap_test.go ├── build ├── gen-codes-validate │ ├── README.md │ └── main.go └── gen-codes │ ├── main.go │ └── parser │ ├── generate.go │ └── process.go ├── cmd ├── evtest │ └── main.go └── uinputtest │ └── main.go ├── codes.go ├── device.go ├── go.mod ├── ioctl.go ├── list.go ├── names.go ├── types.go └── uinput.go /.gitignore: -------------------------------------------------------------------------------- 1 | /evtest 2 | /uinputtest 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2019 Holoplot GmbH 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go support for the Linux evdev interface 2 | 3 | This is a pure Go package for the Linux evdev interface, without cgo dependencies. 4 | 5 | The Linux evdev interface is the userspace interface to interact with input devices such as 6 | keyboard, mice, joysticks, touchscreens, rotary encoders etc. 7 | 8 | The implementation in this package has the following features: 9 | 10 | * Query device information such as the name, the physical location, the unique ID, 11 | the vendor/product/bus/version IDs 12 | * Query supported event types, codes and device properties 13 | * Query the current status of bit-field based input types (such as keyboard, switches etc) 14 | as well as information on absolute types (`ABS_X`, ...) including their min/max values and 15 | current state 16 | * Grab/Ungrab/Revoke support for exclusive claiming of devices 17 | * Auto-generated `const` definitions and maps for types and codes from the kernel include headers 18 | 19 | # Install 20 | 21 | ``` 22 | go get github.com/holoplot/go-evdev 23 | ``` 24 | 25 | And then use it in your source code. 26 | 27 | ``` 28 | import "github.com/holoplot/go-evdev" 29 | ``` 30 | 31 | # Re-generating codes.go 32 | 33 | To re-generate `codes.go` from the latest kernel headers, use the following command. 34 | 35 | ``` 36 | go run build/gen-codes/main.go 37 | ``` 38 | 39 | You can optionally validate generated string mappings with `go run build/gen-codes-validate/main.go` 40 | 41 | # Example 42 | 43 | See the code in `cmd/evtest` for an example. 44 | 45 | # MIT License 46 | 47 | See file `LICENSE` for details. 48 | -------------------------------------------------------------------------------- /bitmap.go: -------------------------------------------------------------------------------- 1 | package evdev 2 | 3 | type bitmap struct { 4 | bits []byte 5 | } 6 | 7 | func (bm *bitmap) bitIsSet(bit int) bool { 8 | if bit > len(bm.bits)*8 { 9 | return false 10 | } 11 | 12 | return bm.bits[bit/8]&(1<<(bit%8)) != 0 13 | } 14 | 15 | func (bm *bitmap) setBits() []int { 16 | var a []int 17 | 18 | for i, by := range bm.bits { 19 | for bit := 0; bit < 8; bit++ { 20 | if by&byte(1<from direction 70 | for k1, v := range to { 71 | k2, ok := from[v] 72 | if !ok { 73 | fmt.Printf("- missing fromString item! key: %v (expected value: %4d / 0x%04x)\n", v, k1, k1) 74 | invalidMapping++ 75 | continue 76 | } 77 | if k1 != k2 { 78 | fmt.Printf("- different fromString value! key: %v, expected: %v, got: %v\n", v, k1, k2) 79 | invalidMapping++ 80 | continue 81 | } 82 | validMapping++ 83 | } 84 | 85 | // test mapping in from>to direction 86 | for k1, v := range from { 87 | k2, ok := to[v] 88 | if !ok { 89 | fmt.Printf("- missing toString item! key: %4d / 0x%04x (expected value: %v)\n", v, v, k1) 90 | invalidMapping++ 91 | continue 92 | } 93 | if k1 != k2 { 94 | // may be different due to value duplication 95 | if contains(duplicatedVal[v], k1) { 96 | duplicationMapping++ 97 | continue 98 | } 99 | fmt.Printf("- different toString value! key: %v, expected: %v, got: %v\n", v, k1, k2) 100 | invalidMapping++ 101 | continue 102 | } 103 | 104 | validMapping++ 105 | } 106 | } 107 | 108 | func main() { 109 | for _, p := range testingSet { 110 | fmt.Printf("Analyzing \"%s\" group...\n", p.name) 111 | switch to := p.toString.(type) { 112 | case evCodeToString: 113 | switch from := p.fromString.(type) { 114 | case evCodeFromString: 115 | compareGroups(from, to) 116 | case evPropFromString, evTypeFromString: 117 | panic("type mismatch") 118 | default: 119 | panic("unexpected type") 120 | } 121 | case evPropToString: 122 | switch from := p.fromString.(type) { 123 | case evPropFromString: 124 | compareGroups(from, to) 125 | case evCodeFromString, evTypeFromString: 126 | panic("type mismatch") 127 | default: 128 | panic("unexpected type") 129 | } 130 | case evTypeToString: 131 | switch from := p.fromString.(type) { 132 | case evTypeFromString: 133 | compareGroups(from, to) 134 | case evCodeFromString, evPropFromString: 135 | panic("type mismatch") 136 | default: 137 | panic("unexpected type") 138 | } 139 | default: 140 | panic("unexpected type") 141 | } 142 | } 143 | 144 | fmt.Printf( 145 | "\nvalid mappings: %d,\nignored due to key value duplication: %d,\ninvalid mappings: %d\n\n", 146 | validMapping, duplicationMapping, invalidMapping, 147 | ) 148 | if invalidMapping > 0 { 149 | fmt.Printf("detected invalid mappings!\n") 150 | os.Exit(1) 151 | } 152 | 153 | fmt.Printf("all good\n") 154 | os.Exit(0) 155 | } 156 | -------------------------------------------------------------------------------- /build/gen-codes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "go/format" 8 | "io" 9 | "net/http" 10 | "os" 11 | "regexp" 12 | "strings" 13 | "time" 14 | 15 | "github.com/holoplot/go-evdev/build/gen-codes/parser" 16 | ) 17 | 18 | const ( 19 | eventCodes = "include/uapi/linux/input-event-codes.h" 20 | inputH = "include/uapi/linux/input.h" 21 | ) 22 | 23 | func downloadFile(url string) []byte { 24 | client := http.Client{ 25 | Timeout: time.Second * 10, 26 | } 27 | 28 | resp, err := client.Get(url) 29 | if err != nil { 30 | panic(fmt.Errorf("downlload \"%s\" file failed: %v", url, err)) 31 | } 32 | 33 | data, err := io.ReadAll(resp.Body) 34 | if err != nil { 35 | panic(fmt.Errorf("reading data of \"%s\" file failed: %v", url, err)) 36 | } 37 | 38 | return data 39 | } 40 | 41 | type Tag struct { 42 | Ref string `json:"ref"` 43 | } 44 | 45 | func getTags() []string { 46 | var tagRegex = regexp.MustCompile(`^refs/tags/(?Pv(\.?\d+)+)$`) 47 | var tags []Tag 48 | 49 | url := "https://api.github.com/repos/torvalds/linux/git/refs/tags" 50 | err := json.Unmarshal(downloadFile(url), &tags) 51 | if err != nil { 52 | panic(fmt.Errorf("failed to parse json \"%s\" file: %v", url, err)) 53 | } 54 | 55 | var tagsString []string 56 | 57 | for _, t := range tags { 58 | match := tagRegex.FindStringSubmatch(t.Ref) 59 | if match == nil { 60 | continue 61 | } 62 | 63 | tagsString = append(tagsString, match[1]) 64 | } 65 | 66 | return tagsString 67 | } 68 | 69 | func main() { 70 | var disableComments, showTags bool 71 | var gitTag string 72 | 73 | flag.BoolVar( 74 | &disableComments, "disableComments", false, 75 | "disable including comments in the output file", 76 | ) 77 | flag.StringVar(&gitTag, "tag", "", "select precise tag release of Linux") 78 | flag.BoolVar(&showTags, "tags", false, "list available Linux tag releases") 79 | flag.Parse() 80 | 81 | fmt.Println("Fetching tags...") 82 | tags := getTags() 83 | 84 | if len(tags) == 0 { 85 | fmt.Printf("no tags found\n") 86 | os.Exit(1) 87 | } 88 | 89 | newestTag := tags[len(tags)-1] 90 | 91 | fmt.Printf("The newest available tag: %s\n", newestTag) 92 | if showTags { 93 | for _, tag := range tags { 94 | fmt.Printf("- %s\n", tag) 95 | } 96 | os.Exit(0) 97 | } 98 | 99 | var selectedTag = newestTag 100 | if gitTag != "" { 101 | var found bool 102 | for _, tag := range tags { 103 | if tag == gitTag { 104 | found = true 105 | break 106 | } 107 | } 108 | if !found { 109 | fmt.Printf("tag \"%s\" does not exist\n", gitTag) 110 | os.Exit(1) 111 | } 112 | selectedTag = gitTag 113 | fmt.Printf("found \"%s\" tag\n", gitTag) 114 | fmt.Printf("Warning! This codegen was not tested with heavily outdated releases\n") 115 | fmt.Printf("nor the code that depends on it.\n") 116 | } 117 | 118 | urlBase := "https://raw.githubusercontent.com/torvalds/linux/%s/%s" 119 | inputHURL := fmt.Sprintf(urlBase, selectedTag, inputH) 120 | eventCodesURL := fmt.Sprintf(urlBase, selectedTag, eventCodes) 121 | 122 | fmt.Println("Downloading files...") 123 | fmt.Printf("- %s\n- %s\n", inputHURL, eventCodesURL) 124 | inputHContent := string(downloadFile(inputHURL)) 125 | eventCodesContent := string(downloadFile(eventCodesURL)) 126 | 127 | c1 := parser.NewCodeProcessor(parser.SelectedPrefixesGroups["input.h"]) 128 | c2 := parser.NewCodeProcessor(parser.SelectedPrefixesGroups["input-event-codes.h"]) 129 | 130 | fmt.Println("Processing files...") 131 | 132 | elements1, err := c1.ProcessFile(strings.NewReader(inputHContent)) 133 | if err != nil { 134 | fmt.Printf("processing input.h file failed: %v\n", err) 135 | os.Exit(1) 136 | } 137 | elements2, err := c2.ProcessFile(strings.NewReader(eventCodesContent)) 138 | if err != nil { 139 | fmt.Printf("processingi nput-event-codes.h file failed: %v\n", err) 140 | os.Exit(1) 141 | } 142 | 143 | allElements := append(elements2, elements1...) 144 | 145 | fmt.Println("Generating file...") 146 | data := parser.GenerateFile(allElements, disableComments, selectedTag, inputHURL, eventCodesURL) 147 | 148 | formatted, err := format.Source([]byte(data)) 149 | if err != nil { 150 | fmt.Printf("Cannot format: %s", err) 151 | os.Exit(1) 152 | } 153 | fileName := "codes.go" 154 | if err := os.WriteFile(fileName, formatted, 0o644); err != nil { 155 | fmt.Printf("Failed to write data to %s file: %v", fileName, err) 156 | os.Exit(1) 157 | } 158 | 159 | fmt.Println("Done!") 160 | } 161 | -------------------------------------------------------------------------------- /build/gen-codes/parser/generate.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | var typeNames = map[string]string{ 10 | "EV_": "EvType", 11 | "INPUT_PROP_": "EvProp", 12 | } 13 | 14 | func getType(in string) string { 15 | for k, v := range typeNames { 16 | if strings.HasPrefix(in, k) { 17 | return v 18 | } 19 | } 20 | return "EvCode" 21 | } 22 | 23 | var SelectedPrefixesGroups = map[string][][]string{ 24 | // "Group" detection relies on the correct order of these set of prefixes 25 | // this order should reflect exact order of groups in related source files 26 | "input.h": { 27 | {"ID_"}, 28 | {"BUS_"}, 29 | {"MT_TOOL_"}, 30 | {"FF_"}, 31 | }, 32 | "input-event-codes.h": { 33 | {"INPUT_PROP_"}, 34 | {"EV_"}, 35 | {"SYN_"}, 36 | {"KEY_", "BTN_"}, // these have different prefixes but belongs to the same group type 37 | {"REL_"}, 38 | {"ABS_"}, 39 | {"SW_"}, 40 | {"MSC_"}, 41 | {"LED_"}, 42 | {"REP_"}, 43 | {"SND_"}, 44 | }, 45 | } 46 | 47 | // stripSeparators removes separators from the begging and the end 48 | func stripSeparators(elements []interface{}) []interface{} { 49 | var start, stop int 50 | 51 | for i, e := range elements { 52 | _, ok := e.(separator) 53 | if !ok { 54 | start = i 55 | break 56 | } 57 | } 58 | 59 | for i, e := range elements { 60 | _, ok := e.(separator) 61 | if !ok { 62 | stop = i 63 | } 64 | } 65 | 66 | return elements[start : stop+1] 67 | } 68 | 69 | type decodedValue struct { 70 | value int 71 | encodingType EncodingType 72 | } 73 | 74 | func removeRepeatedSeparators(groups []Group) []Group { 75 | var newGroups = make([]Group, 0) 76 | 77 | for _, group := range groups { 78 | newGroup := Group{ 79 | comment: group.comment, 80 | elements: make([]interface{}, 0), 81 | } 82 | 83 | var sepPreviously bool 84 | for _, element := range group.elements { 85 | switch element.(type) { 86 | case separator: 87 | if !sepPreviously { 88 | newGroup.elements = append(newGroup.elements, separator("")) 89 | sepPreviously = true 90 | } 91 | default: 92 | sepPreviously = false 93 | newGroup.elements = append(newGroup.elements, element) 94 | } 95 | 96 | } 97 | 98 | newGroups = append(newGroups, newGroup) 99 | } 100 | 101 | return newGroups 102 | } 103 | 104 | func generateSections(rawGroups []Group, disableComments bool) (codes, typeToString, typeFromString, typeNames string) { 105 | groups := removeRepeatedSeparators(rawGroups) 106 | 107 | var decodedValues = make(map[constant]decodedValue) 108 | 109 | for _, group := range groups { 110 | for _, element := range group.elements { 111 | switch v := element.(type) { 112 | case constant: 113 | switch v.encodingType { 114 | case EncodingEquation: 115 | encType, valDecoded, err := v.resolveEquation(&group) 116 | if err != nil { 117 | panic(fmt.Errorf("failed to decode equation: %w", err)) 118 | } 119 | decodedValues[v] = decodedValue{valDecoded, encType} 120 | case EncodingText: 121 | encType, valDecoded, err := v.resolveText(&group) 122 | if err != nil { 123 | panic(fmt.Errorf("failed to decode text: %w", err)) 124 | } 125 | decodedValues[v] = decodedValue{valDecoded, encType} 126 | case EncodingInteger: 127 | i, err := strconv.ParseInt(v.value, 10, 64) 128 | if err != nil { 129 | panic(fmt.Errorf("integer conversion failed: %w", err)) 130 | } 131 | decodedValues[v] = decodedValue{int(i), EncodingInteger} 132 | case EncodingHex: 133 | i, err := strconv.ParseInt(v.value[2:], 16, 64) 134 | if err != nil { 135 | panic(fmt.Errorf("hex conversion failed: %w", err)) 136 | } 137 | decodedValues[v] = decodedValue{int(i), EncodingHex} 138 | } 139 | } 140 | } 141 | } 142 | 143 | for i, group := range groups { 144 | if !disableComments && group.comment != "" { 145 | lines := strings.Split(group.comment, "\n") 146 | for i := 0; i < len(lines); i++ { 147 | cl := lines[i] 148 | if cl != "" { 149 | codes += "// " + cl + "\n" 150 | } 151 | } 152 | } 153 | 154 | codes += "const (\n" 155 | for _, element := range stripSeparators(group.elements) { 156 | switch v := element.(type) { 157 | case separator: // space between blocks 158 | codes += "\n" 159 | case comment: // single comment entry 160 | if disableComments { 161 | continue 162 | } 163 | lines := strings.Split(string(v), "\n") 164 | for i := 0; i < len(lines); i++ { 165 | cl := lines[i] 166 | if cl != "" { 167 | codes += "\t// " + cl + "\n" 168 | } 169 | } 170 | case constant: 171 | if !disableComments && v.comment != "" { 172 | codes += fmt.Sprintf("\t%s = %s // %s\n", v.name, v.value, v.comment) 173 | } else { 174 | codes += fmt.Sprintf("\t%s = %s\n", v.name, v.value) 175 | } 176 | default: 177 | panic("") 178 | } 179 | } 180 | codes += ")\n" 181 | 182 | if i < len(groups) { 183 | codes += "\n" 184 | } 185 | } 186 | 187 | // generating additional mappings 188 | for i, group := range groups { 189 | var firstConstant constant 190 | 191 | for _, element := range group.elements { 192 | c, ok := element.(constant) 193 | if !ok { 194 | continue 195 | } 196 | firstConstant = c 197 | break 198 | } 199 | 200 | parts := strings.Split(firstConstant.name, "_") 201 | name := parts[0] 202 | 203 | var valueRegistered = make(map[int]string) 204 | 205 | typeToString += fmt.Sprintf("var %sToString = map[%s]string{\n", name, getType(firstConstant.name)) 206 | for _, element := range stripSeparators(group.elements) { 207 | switch v := element.(type) { 208 | case separator: 209 | typeToString += "\n" 210 | case constant: 211 | decoded, ok := decodedValues[v] 212 | if !ok { 213 | panic("decoded value not found") 214 | } 215 | if name, ok := valueRegistered[decoded.value]; ok { 216 | typeToString += fmt.Sprintf("\t// %s: \"%s\", // (%s)\n", v.name, v.name, name) 217 | continue 218 | } 219 | 220 | switch decoded.encodingType { 221 | case EncodingHex, EncodingInteger: 222 | typeToString += fmt.Sprintf("\t%s: \"%s\",\n", v.name, v.name) 223 | valueRegistered[decoded.value] = v.name 224 | default: 225 | panic("unexpected encoding type") 226 | } 227 | } 228 | } 229 | 230 | typeFromString += fmt.Sprintf("var %sFromString = map[string]%s{\n", name, getType(firstConstant.name)) 231 | for _, element := range stripSeparators(group.elements) { 232 | switch v := element.(type) { 233 | case separator: 234 | typeFromString += "\n" 235 | case constant: 236 | typeFromString += fmt.Sprintf("\t\"%s\": %s,\n", v.name, v.name) 237 | } 238 | } 239 | 240 | valueRegistered = make(map[int]string) 241 | duplicates := make(map[int][]string) 242 | for _, e := range group.elements { 243 | re, ok := e.(constant) 244 | if !ok { 245 | continue 246 | } 247 | decoded, ok := decodedValues[re] 248 | if !ok { 249 | panic("decoded value not found") 250 | } 251 | 252 | duplicates[decoded.value] = append(duplicates[decoded.value], re.name) 253 | } 254 | 255 | typeNames += fmt.Sprintf("var %sNames = map[%s]string{\n", name, getType(firstConstant.name)) 256 | for _, element := range stripSeparators(group.elements) { 257 | switch v := element.(type) { 258 | case separator: 259 | typeNames += "\n" 260 | case constant: 261 | decoded, ok := decodedValues[v] 262 | if !ok { 263 | panic("decoded value not found") 264 | } 265 | 266 | if _, ok := valueRegistered[decoded.value]; ok { 267 | continue 268 | } 269 | 270 | var names string 271 | for i, name := range duplicates[decoded.value] { 272 | names += name 273 | if i != len(duplicates[decoded.value])-1 { 274 | names += "/" 275 | } 276 | } 277 | 278 | switch decoded.encodingType { 279 | case EncodingHex, EncodingInteger: 280 | typeNames += fmt.Sprintf("\t%s: \"%s\",\n", v.name, names) 281 | valueRegistered[decoded.value] = v.name 282 | default: 283 | panic("unexpected encoding type") 284 | } 285 | } 286 | } 287 | 288 | typeToString += "}\n" 289 | typeFromString += "}\n" 290 | typeNames += "}\n" 291 | 292 | if i < len(groups) { 293 | typeToString += "\n" 294 | typeFromString += "\n" 295 | typeNames += "\n" 296 | } 297 | } 298 | return 299 | } 300 | 301 | func GenerateFile(rawGroups []Group, disableComments bool, selectedTag, inputHURL, eventCodesURL string) string { 302 | var file string 303 | codes, typeToString, typeFromString, typeNames := generateSections(rawGroups, disableComments) 304 | 305 | file += "// Code generated by build/gen-codes. DO NOT EDIT.\n" 306 | file += fmt.Sprintf("// version tag: \"%s\", generated from files:\n", selectedTag) 307 | file += fmt.Sprintf("// - %s\n", inputHURL) 308 | file += fmt.Sprintf("// - %s\n\n", eventCodesURL) 309 | file += "package evdev\n\n" 310 | file += codes 311 | 312 | file += "\n//\n// Type to String\n//\n\n" 313 | file += typeToString 314 | 315 | file += "\n//\n// Type from String\n//\n\n" 316 | file += typeFromString 317 | 318 | file += "\n//\n// Type Names, useful for information/debug use only.\n" 319 | file += "// When one code has two or more string representations, all available aliases are provided seperated by a slash.\n" 320 | file += "// Example: KEY_COFFEE: \"KEY_COFFEE/KEY_SCREENLOCK\"\n//\n\n" 321 | file += typeNames 322 | 323 | return file 324 | } 325 | -------------------------------------------------------------------------------- /build/gen-codes/parser/process.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "io" 7 | "regexp" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | type EncodingType string 13 | 14 | const ( 15 | EncodingUnknown EncodingType = "" 16 | EncodingHex EncodingType = "hex" 17 | EncodingInteger EncodingType = "int" 18 | EncodingText EncodingType = "text" // e.g. "SOME_OTHER_CONST_NAME" 19 | EncodingEquation EncodingType = "equation" // e.g. "(CONST_NAME + 1)" 20 | ) 21 | 22 | const ( 23 | stateNeutral = iota 24 | stateReadingMultilineComment 25 | stateReadingDefineWithMultilineComment 26 | ) 27 | 28 | var ( 29 | regexHex = regexp.MustCompile(`^0x[0-9a-fA-F]+$`) 30 | regexInteger = regexp.MustCompile(`^[0-9]+$`) 31 | regexText = regexp.MustCompile(`^\w+$`) 32 | regexEquation = regexp.MustCompile(`^\((\w+)\s*(\+)\s*(\d)+\)$`) 33 | ) 34 | 35 | func detectEncodingType(value string) (EncodingType, int) { 36 | var convertedValue int64 37 | var err error 38 | 39 | switch { 40 | case regexHex.MatchString(value): 41 | convertedValue, err = strconv.ParseInt(value[2:], 16, 64) 42 | if err != nil { 43 | panic(err) 44 | } 45 | return EncodingHex, int(convertedValue) 46 | case regexInteger.MatchString(value): 47 | convertedValue, err = strconv.ParseInt(value, 10, 64) 48 | if err != nil { 49 | panic(err) 50 | } 51 | return EncodingInteger, int(convertedValue) 52 | case regexEquation.MatchString(value): 53 | return EncodingEquation, 0 // can't resolve value that points on different constant here 54 | case regexText.MatchString(value): 55 | return EncodingText, 0 // can't resolve value that points on different constant here 56 | default: 57 | return EncodingUnknown, 0 58 | } 59 | } 60 | 61 | type separator string // one line 62 | 63 | type comment string // may be bigger than one line 64 | 65 | type constant struct { 66 | name string 67 | value string 68 | decodedValue int 69 | comment string // oneliner 70 | encodingType EncodingType 71 | } 72 | 73 | func (c *constant) resolveEquation(group *Group) (EncodingType, int, error) { 74 | out := regexEquation.FindStringSubmatch(c.value) 75 | rawA, sign, rawB := out[1], out[2], out[3] 76 | if sign != "+" { 77 | return EncodingUnknown, 0, errors.New("e1") 78 | } 79 | i, err := strconv.ParseInt(rawB, 10, 64) 80 | if err != nil { 81 | return EncodingUnknown, 0, errors.New("e2") 82 | } 83 | 84 | valName, valDecoded := rawA, int(i) 85 | 86 | var found, ok bool 87 | var v2 constant 88 | for _, e := range group.elements { 89 | v2, ok = e.(constant) 90 | if !ok { 91 | continue 92 | } 93 | if v2.name == valName { 94 | found = true 95 | break 96 | } 97 | } 98 | if !found { 99 | return EncodingUnknown, 0, errors.New("value not found") 100 | } 101 | 102 | return v2.encodingType, v2.decodedValue + valDecoded, nil 103 | } 104 | 105 | func (c *constant) resolveText(group *Group) (EncodingType, int, error) { 106 | var found, ok bool 107 | var v2 constant 108 | for _, e := range group.elements { 109 | v2, ok = e.(constant) 110 | if !ok { 111 | continue 112 | } 113 | if v2.name == c.value { 114 | found = true 115 | break 116 | } 117 | } 118 | if !found { 119 | return EncodingUnknown, 0, errors.New("value not found") 120 | } 121 | 122 | return v2.encodingType, v2.decodedValue, nil 123 | } 124 | 125 | // Group contains list of elements (separator, comment or constant) 126 | type Group struct { 127 | comment string 128 | elements []interface{} 129 | } 130 | 131 | func NewGroup() Group { 132 | return Group{ 133 | comment: "", 134 | elements: make([]interface{}, 0), 135 | } 136 | } 137 | 138 | var ( 139 | reDefineWithComment = regexp.MustCompile(`^#define[ \t]+(?P[A-Z0-9_]+)[ \t]+(?P[0-9a-fA-Zx()_+ ]+)[ \t]+/\*(?P.*)\*/[ \t]*$`) 140 | reDefineWithCommentStart = regexp.MustCompile(`^#define[ \t]+(?P[A-Z0-9_]+)[ \t]+(?P[0-9a-fA-Zx()_+ ]+)[ \t]+/\*(?P.*)[ \t]*$`) 141 | reDefine = regexp.MustCompile(`^#define[ \t]+(?P[A-Z0-9_]+)[ \t]+(?P[0-9a-fA-Zx()_+ ]+)`) 142 | reOnelineComment = regexp.MustCompile(`^[ \t]*/\*(?P.*)\*/[ \t]*$`) 143 | reMultilineCommentStart = regexp.MustCompile(`^[ \t]*/\*(?P.*)[ \t]*$`) 144 | reMultilineCommentEnd = regexp.MustCompile(`^[ \t](?:\*)?(?P.*)\*/[ \t]*$`) 145 | reMultilineCommentMid = regexp.MustCompile(`^[ \t]*(?:\*)?(?P.*)[ \t]*$`) 146 | ) 147 | 148 | func hasPrefixInSlice(v string, s []string) bool { 149 | for _, vs := range s { 150 | if strings.HasPrefix(v, vs) { 151 | return true 152 | } 153 | } 154 | return false 155 | } 156 | 157 | type CodeProcessor struct { 158 | prefixesGroups [][]string 159 | 160 | elements []interface{} 161 | lastComment string 162 | state int 163 | } 164 | 165 | func NewCodeProcessor(prefixesGroups [][]string) CodeProcessor { 166 | return CodeProcessor{ 167 | prefixesGroups: prefixesGroups, 168 | 169 | elements: make([]interface{}, 0), 170 | lastComment: "", 171 | state: stateNeutral, 172 | } 173 | } 174 | 175 | func (p *CodeProcessor) ProcessFile(file io.Reader) ([]Group, error) { 176 | var groups = make([]Group, 0) 177 | var group = NewGroup() 178 | 179 | var variable constant 180 | var suffixCounter int 181 | var lastComment string 182 | var sepAfterComment bool 183 | var groupCommentAdded bool 184 | var seeking = true 185 | var currentPrefixes = p.prefixesGroups[suffixCounter] 186 | 187 | scanner := bufio.NewScanner(file) 188 | 189 | scanning: 190 | for scanner.Scan() { 191 | s := scanner.Text() 192 | 193 | switch p.state { 194 | case stateNeutral: 195 | if match := reDefine.FindStringSubmatch(s); match != nil { 196 | if !hasPrefixInSlice(match[1], currentPrefixes) { // exiting type group 197 | if seeking { 198 | continue // seeking through #define elements and preserving last comment in the meantime 199 | } 200 | groups = append(groups, group) 201 | suffixCounter++ 202 | if suffixCounter == len(p.prefixesGroups) { 203 | break scanning 204 | } 205 | group = NewGroup() 206 | groupCommentAdded = false 207 | currentPrefixes = p.prefixesGroups[suffixCounter] 208 | } 209 | seeking = false 210 | 211 | if lastComment != "" && !groupCommentAdded { 212 | group.comment = lastComment 213 | groupCommentAdded = true 214 | lastComment = "" 215 | } 216 | 217 | if lastComment != "" { 218 | group.elements = append(group.elements, comment(lastComment)) 219 | lastComment = "" 220 | if sepAfterComment { 221 | group.elements = append(group.elements, separator("")) 222 | } 223 | } 224 | } 225 | 226 | if match := reDefineWithComment.FindStringSubmatch(s); match != nil { 227 | variable.name, variable.value, variable.comment = match[1], match[2], strings.Trim(match[3], " \t") 228 | variable.value = strings.Trim(variable.value, " \t") 229 | variable.encodingType, variable.decodedValue = detectEncodingType(variable.value) 230 | group.elements = append(group.elements, variable) 231 | continue 232 | } 233 | 234 | if match := reDefineWithCommentStart.FindStringSubmatch(s); match != nil { 235 | variable.name, variable.value, variable.comment = match[1], match[2], strings.Trim(match[3], " \t") 236 | variable.value = strings.Trim(variable.value, " \t") 237 | variable.encodingType, variable.decodedValue = detectEncodingType(variable.value) 238 | p.state = stateReadingDefineWithMultilineComment 239 | continue 240 | } 241 | 242 | if match := reDefine.FindStringSubmatch(s); match != nil { 243 | variable.name, variable.value, variable.comment = match[1], match[2], "" 244 | variable.value = strings.Trim(variable.value, " \t") 245 | variable.encodingType, variable.decodedValue = detectEncodingType(variable.value) 246 | group.elements = append(group.elements, variable) 247 | continue 248 | } 249 | 250 | if match := reOnelineComment.FindStringSubmatch(s); match != nil { 251 | lastComment = strings.Trim(match[1], " \t") 252 | continue 253 | } 254 | 255 | if match := reMultilineCommentStart.FindStringSubmatch(s); match != nil { 256 | lastComment = "" 257 | if len(match[1]) > 0 { 258 | lastComment += strings.Trim(match[1], " \t") 259 | } 260 | p.state = stateReadingMultilineComment 261 | continue 262 | } 263 | 264 | if s == "" { 265 | sepAfterComment = true 266 | group.elements = append(group.elements, separator("")) 267 | continue 268 | } else { 269 | sepAfterComment = false 270 | } 271 | 272 | case stateReadingDefineWithMultilineComment: 273 | if match := reMultilineCommentEnd.FindStringSubmatch(s); match != nil { 274 | if len(match[1]) > 0 { 275 | variable.comment += strings.Trim(match[1], " \t") + "\n" 276 | } 277 | group.elements = append(group.elements, variable) 278 | p.state = stateNeutral 279 | continue 280 | } 281 | 282 | if match := reMultilineCommentMid.FindStringSubmatch(s); match != nil { 283 | if len(match[1]) > 0 { 284 | variable.comment += strings.Trim(match[1], " \t") 285 | } 286 | continue 287 | } 288 | 289 | return groups, errors.New("processing should not reach this point: #1") 290 | 291 | case stateReadingMultilineComment: 292 | if match := reMultilineCommentEnd.FindStringSubmatch(s); match != nil { 293 | if len(match[1]) > 0 { 294 | lastComment += " " + strings.Trim(match[1], " \t") 295 | } 296 | lastComment += match[1] 297 | p.state = stateNeutral 298 | continue 299 | } 300 | 301 | if match := reMultilineCommentMid.FindStringSubmatch(s); match != nil { 302 | if len(match[1]) > 0 { 303 | lastComment += strings.Trim(match[1], " \t") + "\n" 304 | } 305 | continue 306 | } 307 | 308 | return groups, errors.New("processing should not reach this point: #2") 309 | } 310 | } 311 | groups = append(groups, group) 312 | return groups, nil 313 | } 314 | -------------------------------------------------------------------------------- /cmd/evtest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/holoplot/go-evdev" 8 | ) 9 | 10 | func listDevices() { 11 | devicePaths, err := evdev.ListDevicePaths() 12 | if err != nil { 13 | fmt.Printf("Cannot list device paths: %s", err) 14 | return 15 | } 16 | for _, d := range devicePaths { 17 | fmt.Printf("%s:\t%s\n", d.Path, d.Name) 18 | } 19 | } 20 | 21 | func main() { 22 | if len(os.Args) < 2 { 23 | fmt.Printf("Usage: %s \n\n", os.Args[0]) 24 | fmt.Printf("Available devices:\n") 25 | 26 | listDevices() 27 | return 28 | } 29 | 30 | d, err := evdev.Open(os.Args[1]) 31 | if err != nil { 32 | fmt.Printf("Cannot read %s: %v\n", os.Args[1], err) 33 | return 34 | } 35 | 36 | vMajor, vMinor, vMicro := d.DriverVersion() 37 | fmt.Printf("Input driver version is %d.%d.%d\n", vMajor, vMinor, vMicro) 38 | 39 | inputID, err := d.InputID() 40 | if err == nil { 41 | fmt.Printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", 42 | inputID.BusType, inputID.Vendor, inputID.Product, inputID.Version) 43 | } 44 | 45 | name, err := d.Name() 46 | if err == nil { 47 | fmt.Printf("Input device name: \"%s\"\n", name) 48 | } 49 | 50 | phys, err := d.PhysicalLocation() 51 | if err == nil { 52 | fmt.Printf("Input device physical location: %s\n", phys) 53 | } 54 | 55 | uniq, err := d.UniqueID() 56 | if err == nil { 57 | fmt.Printf("Input device unique ID: %s\n", uniq) 58 | } 59 | 60 | fmt.Printf("Supported events:\n") 61 | 62 | for _, t := range d.CapableTypes() { 63 | fmt.Printf(" Event type %d (%s)\n", t, evdev.TypeName(t)) 64 | 65 | state, err := d.State(t) 66 | if err == nil { 67 | for code, value := range state { 68 | fmt.Printf(" Event code %d (%s) state %v\n", code, evdev.CodeName(t, code), value) 69 | } 70 | } 71 | 72 | if t != evdev.EV_ABS { 73 | continue 74 | } 75 | 76 | absInfos, err := d.AbsInfos() 77 | if err != nil { 78 | continue 79 | } 80 | 81 | for code, absInfo := range absInfos { 82 | fmt.Printf(" Event code %d (%s)\n", code, evdev.CodeName(t, code)) 83 | fmt.Printf(" Value: %d\n", absInfo.Value) 84 | fmt.Printf(" Min: %d\n", absInfo.Minimum) 85 | fmt.Printf(" Max: %d\n", absInfo.Maximum) 86 | 87 | if absInfo.Fuzz != 0 { 88 | fmt.Printf(" Fuzz: %d\n", absInfo.Fuzz) 89 | } 90 | if absInfo.Flat != 0 { 91 | fmt.Printf(" Flat: %d\n", absInfo.Flat) 92 | } 93 | if absInfo.Resolution != 0 { 94 | fmt.Printf(" Resolution: %d\n", absInfo.Resolution) 95 | } 96 | } 97 | } 98 | 99 | fmt.Printf("Properties:\n") 100 | 101 | props := d.Properties() 102 | 103 | for _, p := range props { 104 | fmt.Printf(" Property type %d (%s)\n", p, evdev.PropName(p)) 105 | } 106 | 107 | fmt.Printf("Testing ... (interrupt to exit)\n") 108 | 109 | for { 110 | e, err := d.ReadOne() 111 | if err != nil { 112 | fmt.Printf("Error reading from device: %v\n", err) 113 | return 114 | } 115 | 116 | ts := fmt.Sprintf("Event: time %d.%06d", e.Time.Sec, e.Time.Usec) 117 | 118 | switch e.Type { 119 | case evdev.EV_SYN: 120 | switch e.Code { 121 | case evdev.SYN_MT_REPORT: 122 | fmt.Printf("%s, ++++++++++++++ %s ++++++++++++\n", ts, e.CodeName()) 123 | case evdev.SYN_DROPPED: 124 | fmt.Printf("%s, >>>>>>>>>>>>>> %s <<<<<<<<<<<<\n", ts, e.CodeName()) 125 | default: 126 | fmt.Printf("%s, -------------- %s ------------\n", ts, e.CodeName()) 127 | } 128 | default: 129 | fmt.Printf("%s, %s\n", ts, e.String()) 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /cmd/uinputtest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | 9 | "github.com/holoplot/go-evdev" 10 | ) 11 | 12 | func listDevices() { 13 | devicePaths, err := evdev.ListDevicePaths() 14 | if err != nil { 15 | fmt.Printf("Cannot list device paths: %s", err) 16 | return 17 | } 18 | for _, d := range devicePaths { 19 | fmt.Printf("%s:\t%s\n", d.Path, d.Name) 20 | } 21 | } 22 | 23 | func cloneDevice(devicePath string) { 24 | targetDev, err := evdev.Open(devicePath) 25 | if err != nil { 26 | fmt.Printf("failed to open target device for cloning: %s", err.Error()) 27 | return 28 | 29 | } 30 | defer targetDev.Close() 31 | 32 | clonedDev, err := evdev.CloneDevice("my-device-clone", targetDev) 33 | if err != nil { 34 | fmt.Printf("failed to clone device: %s", err.Error()) 35 | return 36 | } 37 | defer clonedDev.Close() 38 | 39 | moveMouse(clonedDev) 40 | } 41 | 42 | func createDevice() { 43 | dev, err := evdev.CreateDevice( 44 | "fake-device", 45 | evdev.InputID{ 46 | BusType: 0x03, 47 | Vendor: 0x4711, 48 | Product: 0x0816, 49 | Version: 1, 50 | }, 51 | map[evdev.EvType][]evdev.EvCode{ 52 | evdev.EV_KEY: { 53 | evdev.BTN_LEFT, 54 | evdev.BTN_RIGHT, 55 | evdev.BTN_MIDDLE, 56 | }, 57 | evdev.EV_REL: { 58 | evdev.REL_X, 59 | evdev.REL_Y, 60 | evdev.REL_WHEEL, 61 | evdev.REL_HWHEEL, 62 | }, 63 | }, 64 | ) 65 | if err != nil { 66 | fmt.Printf("failed to create device: %s", err.Error()) 67 | return 68 | } 69 | // defer dev.Close() 70 | 71 | moveMouse(dev) 72 | } 73 | 74 | func moveMouse(dev *evdev.InputDevice) { 75 | fmt.Println("Moving the mouse...") 76 | for i := 0; i < 400; i++ { 77 | time.Sleep(10 * time.Millisecond) 78 | 79 | evTime := syscall.NsecToTimeval(int64(time.Now().Nanosecond())) 80 | 81 | if i < 100 { 82 | dev.WriteOne(&evdev.InputEvent{ 83 | Time: evTime, 84 | Type: evdev.EV_REL, 85 | Code: evdev.REL_X, 86 | Value: 2, 87 | }) 88 | } else if i < 200 { 89 | dev.WriteOne(&evdev.InputEvent{ 90 | Time: evTime, 91 | Type: evdev.EV_REL, 92 | Code: evdev.REL_Y, 93 | Value: 2, 94 | }) 95 | } else if i < 300 { 96 | dev.WriteOne(&evdev.InputEvent{ 97 | Time: evTime, 98 | Type: evdev.EV_REL, 99 | Code: evdev.REL_X, 100 | Value: -2, 101 | }) 102 | } else { 103 | dev.WriteOne(&evdev.InputEvent{ 104 | Time: evTime, 105 | Type: evdev.EV_REL, 106 | Code: evdev.REL_Y, 107 | Value: -2, 108 | }) 109 | } 110 | 111 | dev.WriteOne(&evdev.InputEvent{ 112 | Time: evTime, 113 | Type: evdev.EV_SYN, 114 | Code: evdev.SYN_REPORT, 115 | Value: 0, 116 | }) 117 | } 118 | 119 | fmt.Println("Done!") 120 | } 121 | 122 | func usage() { 123 | fmt.Print("Create a new input device, or clone capabiliies from an existing one\n\n") 124 | fmt.Printf("Usage: %s clone [input device]\n", os.Args[0]) 125 | fmt.Printf(" %s create\n\n", os.Args[0]) 126 | fmt.Printf("Available devices:\n") 127 | 128 | listDevices() 129 | } 130 | 131 | func main() { 132 | if len(os.Args) < 2 { 133 | usage() 134 | return 135 | } 136 | 137 | switch os.Args[1] { 138 | case "clone": 139 | if len(os.Args) < 3 { 140 | usage() 141 | return 142 | } 143 | 144 | cloneDevice(os.Args[2]) 145 | 146 | case "create": 147 | createDevice() 148 | 149 | default: 150 | usage() 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /codes.go: -------------------------------------------------------------------------------- 1 | // Code generated by build/gen-codes. DO NOT EDIT. 2 | // version tag: "v6.7", generated from files: 3 | // - https://raw.githubusercontent.com/torvalds/linux/v6.7/include/uapi/linux/input.h 4 | // - https://raw.githubusercontent.com/torvalds/linux/v6.7/include/uapi/linux/input-event-codes.h 5 | 6 | package evdev 7 | 8 | // Device properties and quirks 9 | const ( 10 | INPUT_PROP_POINTER = 0x00 // needs a pointer 11 | INPUT_PROP_DIRECT = 0x01 // direct input devices 12 | INPUT_PROP_BUTTONPAD = 0x02 // has button(s) under pad 13 | INPUT_PROP_SEMI_MT = 0x03 // touch rectangle only 14 | INPUT_PROP_TOPBUTTONPAD = 0x04 // softbuttons at top of pad 15 | INPUT_PROP_POINTING_STICK = 0x05 // is a pointing stick 16 | INPUT_PROP_ACCELEROMETER = 0x06 // has accelerometer 17 | 18 | INPUT_PROP_MAX = 0x1f 19 | INPUT_PROP_CNT = (INPUT_PROP_MAX + 1) 20 | ) 21 | 22 | // Event types 23 | const ( 24 | EV_SYN = 0x00 25 | EV_KEY = 0x01 26 | EV_REL = 0x02 27 | EV_ABS = 0x03 28 | EV_MSC = 0x04 29 | EV_SW = 0x05 30 | EV_LED = 0x11 31 | EV_SND = 0x12 32 | EV_REP = 0x14 33 | EV_FF = 0x15 34 | EV_PWR = 0x16 35 | EV_FF_STATUS = 0x17 36 | EV_MAX = 0x1f 37 | EV_CNT = (EV_MAX + 1) 38 | ) 39 | 40 | // Synchronization events. 41 | const ( 42 | SYN_REPORT = 0 43 | SYN_CONFIG = 1 44 | SYN_MT_REPORT = 2 45 | SYN_DROPPED = 3 46 | SYN_MAX = 0xf 47 | SYN_CNT = (SYN_MAX + 1) 48 | ) 49 | 50 | // Keys and buttons 51 | // Most of the keys/buttons are modeled after USB HUT 1.12 52 | // (see http://www.usb.org/developers/hidpage). 53 | // Abbreviations in the comments: 54 | // AC - Application Control 55 | // AL - Application Launch Button 56 | // SC - System Control 57 | const ( 58 | KEY_RESERVED = 0 59 | KEY_ESC = 1 60 | KEY_1 = 2 61 | KEY_2 = 3 62 | KEY_3 = 4 63 | KEY_4 = 5 64 | KEY_5 = 6 65 | KEY_6 = 7 66 | KEY_7 = 8 67 | KEY_8 = 9 68 | KEY_9 = 10 69 | KEY_0 = 11 70 | KEY_MINUS = 12 71 | KEY_EQUAL = 13 72 | KEY_BACKSPACE = 14 73 | KEY_TAB = 15 74 | KEY_Q = 16 75 | KEY_W = 17 76 | KEY_E = 18 77 | KEY_R = 19 78 | KEY_T = 20 79 | KEY_Y = 21 80 | KEY_U = 22 81 | KEY_I = 23 82 | KEY_O = 24 83 | KEY_P = 25 84 | KEY_LEFTBRACE = 26 85 | KEY_RIGHTBRACE = 27 86 | KEY_ENTER = 28 87 | KEY_LEFTCTRL = 29 88 | KEY_A = 30 89 | KEY_S = 31 90 | KEY_D = 32 91 | KEY_F = 33 92 | KEY_G = 34 93 | KEY_H = 35 94 | KEY_J = 36 95 | KEY_K = 37 96 | KEY_L = 38 97 | KEY_SEMICOLON = 39 98 | KEY_APOSTROPHE = 40 99 | KEY_GRAVE = 41 100 | KEY_LEFTSHIFT = 42 101 | KEY_BACKSLASH = 43 102 | KEY_Z = 44 103 | KEY_X = 45 104 | KEY_C = 46 105 | KEY_V = 47 106 | KEY_B = 48 107 | KEY_N = 49 108 | KEY_M = 50 109 | KEY_COMMA = 51 110 | KEY_DOT = 52 111 | KEY_SLASH = 53 112 | KEY_RIGHTSHIFT = 54 113 | KEY_KPASTERISK = 55 114 | KEY_LEFTALT = 56 115 | KEY_SPACE = 57 116 | KEY_CAPSLOCK = 58 117 | KEY_F1 = 59 118 | KEY_F2 = 60 119 | KEY_F3 = 61 120 | KEY_F4 = 62 121 | KEY_F5 = 63 122 | KEY_F6 = 64 123 | KEY_F7 = 65 124 | KEY_F8 = 66 125 | KEY_F9 = 67 126 | KEY_F10 = 68 127 | KEY_NUMLOCK = 69 128 | KEY_SCROLLLOCK = 70 129 | KEY_KP7 = 71 130 | KEY_KP8 = 72 131 | KEY_KP9 = 73 132 | KEY_KPMINUS = 74 133 | KEY_KP4 = 75 134 | KEY_KP5 = 76 135 | KEY_KP6 = 77 136 | KEY_KPPLUS = 78 137 | KEY_KP1 = 79 138 | KEY_KP2 = 80 139 | KEY_KP3 = 81 140 | KEY_KP0 = 82 141 | KEY_KPDOT = 83 142 | 143 | KEY_ZENKAKUHANKAKU = 85 144 | KEY_102ND = 86 145 | KEY_F11 = 87 146 | KEY_F12 = 88 147 | KEY_RO = 89 148 | KEY_KATAKANA = 90 149 | KEY_HIRAGANA = 91 150 | KEY_HENKAN = 92 151 | KEY_KATAKANAHIRAGANA = 93 152 | KEY_MUHENKAN = 94 153 | KEY_KPJPCOMMA = 95 154 | KEY_KPENTER = 96 155 | KEY_RIGHTCTRL = 97 156 | KEY_KPSLASH = 98 157 | KEY_SYSRQ = 99 158 | KEY_RIGHTALT = 100 159 | KEY_LINEFEED = 101 160 | KEY_HOME = 102 161 | KEY_UP = 103 162 | KEY_PAGEUP = 104 163 | KEY_LEFT = 105 164 | KEY_RIGHT = 106 165 | KEY_END = 107 166 | KEY_DOWN = 108 167 | KEY_PAGEDOWN = 109 168 | KEY_INSERT = 110 169 | KEY_DELETE = 111 170 | KEY_MACRO = 112 171 | KEY_MUTE = 113 172 | KEY_VOLUMEDOWN = 114 173 | KEY_VOLUMEUP = 115 174 | KEY_POWER = 116 // SC System Power Down 175 | KEY_KPEQUAL = 117 176 | KEY_KPPLUSMINUS = 118 177 | KEY_PAUSE = 119 178 | KEY_SCALE = 120 // AL Compiz Scale (Expose) 179 | 180 | KEY_KPCOMMA = 121 181 | KEY_HANGEUL = 122 182 | KEY_HANGUEL = KEY_HANGEUL 183 | KEY_HANJA = 123 184 | KEY_YEN = 124 185 | KEY_LEFTMETA = 125 186 | KEY_RIGHTMETA = 126 187 | KEY_COMPOSE = 127 188 | 189 | KEY_STOP = 128 // AC Stop 190 | KEY_AGAIN = 129 191 | KEY_PROPS = 130 // AC Properties 192 | KEY_UNDO = 131 // AC Undo 193 | KEY_FRONT = 132 194 | KEY_COPY = 133 // AC Copy 195 | KEY_OPEN = 134 // AC Open 196 | KEY_PASTE = 135 // AC Paste 197 | KEY_FIND = 136 // AC Search 198 | KEY_CUT = 137 // AC Cut 199 | KEY_HELP = 138 // AL Integrated Help Center 200 | KEY_MENU = 139 // Menu (show menu) 201 | KEY_CALC = 140 // AL Calculator 202 | KEY_SETUP = 141 203 | KEY_SLEEP = 142 // SC System Sleep 204 | KEY_WAKEUP = 143 // System Wake Up 205 | KEY_FILE = 144 // AL Local Machine Browser 206 | KEY_SENDFILE = 145 207 | KEY_DELETEFILE = 146 208 | KEY_XFER = 147 209 | KEY_PROG1 = 148 210 | KEY_PROG2 = 149 211 | KEY_WWW = 150 // AL Internet Browser 212 | KEY_MSDOS = 151 213 | KEY_COFFEE = 152 // AL Terminal Lock/Screensaver 214 | KEY_SCREENLOCK = KEY_COFFEE 215 | KEY_ROTATE_DISPLAY = 153 // Display orientation for e.g. tablets 216 | KEY_DIRECTION = KEY_ROTATE_DISPLAY 217 | KEY_CYCLEWINDOWS = 154 218 | KEY_MAIL = 155 219 | KEY_BOOKMARKS = 156 // AC Bookmarks 220 | KEY_COMPUTER = 157 221 | KEY_BACK = 158 // AC Back 222 | KEY_FORWARD = 159 // AC Forward 223 | KEY_CLOSECD = 160 224 | KEY_EJECTCD = 161 225 | KEY_EJECTCLOSECD = 162 226 | KEY_NEXTSONG = 163 227 | KEY_PLAYPAUSE = 164 228 | KEY_PREVIOUSSONG = 165 229 | KEY_STOPCD = 166 230 | KEY_RECORD = 167 231 | KEY_REWIND = 168 232 | KEY_PHONE = 169 // Media Select Telephone 233 | KEY_ISO = 170 234 | KEY_CONFIG = 171 // AL Consumer Control Configuration 235 | KEY_HOMEPAGE = 172 // AC Home 236 | KEY_REFRESH = 173 // AC Refresh 237 | KEY_EXIT = 174 // AC Exit 238 | KEY_MOVE = 175 239 | KEY_EDIT = 176 240 | KEY_SCROLLUP = 177 241 | KEY_SCROLLDOWN = 178 242 | KEY_KPLEFTPAREN = 179 243 | KEY_KPRIGHTPAREN = 180 244 | KEY_NEW = 181 // AC New 245 | KEY_REDO = 182 // AC Redo/Repeat 246 | 247 | KEY_F13 = 183 248 | KEY_F14 = 184 249 | KEY_F15 = 185 250 | KEY_F16 = 186 251 | KEY_F17 = 187 252 | KEY_F18 = 188 253 | KEY_F19 = 189 254 | KEY_F20 = 190 255 | KEY_F21 = 191 256 | KEY_F22 = 192 257 | KEY_F23 = 193 258 | KEY_F24 = 194 259 | 260 | KEY_PLAYCD = 200 261 | KEY_PAUSECD = 201 262 | KEY_PROG3 = 202 263 | KEY_PROG4 = 203 264 | KEY_ALL_APPLICATIONS = 204 // AC Desktop Show All Applications 265 | KEY_DASHBOARD = KEY_ALL_APPLICATIONS 266 | KEY_SUSPEND = 205 267 | KEY_CLOSE = 206 // AC Close 268 | KEY_PLAY = 207 269 | KEY_FASTFORWARD = 208 270 | KEY_BASSBOOST = 209 271 | KEY_PRINT = 210 // AC Print 272 | KEY_HP = 211 273 | KEY_CAMERA = 212 274 | KEY_SOUND = 213 275 | KEY_QUESTION = 214 276 | KEY_EMAIL = 215 277 | KEY_CHAT = 216 278 | KEY_SEARCH = 217 279 | KEY_CONNECT = 218 280 | KEY_FINANCE = 219 // AL Checkbook/Finance 281 | KEY_SPORT = 220 282 | KEY_SHOP = 221 283 | KEY_ALTERASE = 222 284 | KEY_CANCEL = 223 // AC Cancel 285 | KEY_BRIGHTNESSDOWN = 224 286 | KEY_BRIGHTNESSUP = 225 287 | KEY_MEDIA = 226 288 | 289 | KEY_SWITCHVIDEOMODE = 227 // Cycle between available videooutputs (Monitor/LCD/TV-out/etc) 290 | 291 | KEY_KBDILLUMTOGGLE = 228 292 | KEY_KBDILLUMDOWN = 229 293 | KEY_KBDILLUMUP = 230 294 | 295 | KEY_SEND = 231 // AC Send 296 | KEY_REPLY = 232 // AC Reply 297 | KEY_FORWARDMAIL = 233 // AC Forward Msg 298 | KEY_SAVE = 234 // AC Save 299 | KEY_DOCUMENTS = 235 300 | 301 | KEY_BATTERY = 236 302 | 303 | KEY_BLUETOOTH = 237 304 | KEY_WLAN = 238 305 | KEY_UWB = 239 306 | 307 | KEY_UNKNOWN = 240 308 | 309 | KEY_VIDEO_NEXT = 241 // drive next video source 310 | KEY_VIDEO_PREV = 242 // drive previous video source 311 | KEY_BRIGHTNESS_CYCLE = 243 // brightness up, after max is min 312 | KEY_BRIGHTNESS_AUTO = 244 // Set Auto Brightness: manualbrightness control is off,rely on ambient 313 | 314 | KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO 315 | KEY_DISPLAY_OFF = 245 // display device to off state 316 | 317 | KEY_WWAN = 246 // Wireless WAN (LTE, UMTS, GSM, etc.) 318 | KEY_WIMAX = KEY_WWAN 319 | KEY_RFKILL = 247 // Key that controls all radios 320 | 321 | KEY_MICMUTE = 248 // Mute / unmute the microphone 322 | 323 | // Code 255 is reserved for special needs of AT keyboard driver 324 | 325 | BTN_MISC = 0x100 326 | BTN_0 = 0x100 327 | BTN_1 = 0x101 328 | BTN_2 = 0x102 329 | BTN_3 = 0x103 330 | BTN_4 = 0x104 331 | BTN_5 = 0x105 332 | BTN_6 = 0x106 333 | BTN_7 = 0x107 334 | BTN_8 = 0x108 335 | BTN_9 = 0x109 336 | 337 | BTN_MOUSE = 0x110 338 | BTN_LEFT = 0x110 339 | BTN_RIGHT = 0x111 340 | BTN_MIDDLE = 0x112 341 | BTN_SIDE = 0x113 342 | BTN_EXTRA = 0x114 343 | BTN_FORWARD = 0x115 344 | BTN_BACK = 0x116 345 | BTN_TASK = 0x117 346 | 347 | BTN_JOYSTICK = 0x120 348 | BTN_TRIGGER = 0x120 349 | BTN_THUMB = 0x121 350 | BTN_THUMB2 = 0x122 351 | BTN_TOP = 0x123 352 | BTN_TOP2 = 0x124 353 | BTN_PINKIE = 0x125 354 | BTN_BASE = 0x126 355 | BTN_BASE2 = 0x127 356 | BTN_BASE3 = 0x128 357 | BTN_BASE4 = 0x129 358 | BTN_BASE5 = 0x12a 359 | BTN_BASE6 = 0x12b 360 | BTN_DEAD = 0x12f 361 | 362 | BTN_GAMEPAD = 0x130 363 | BTN_SOUTH = 0x130 364 | BTN_A = BTN_SOUTH 365 | BTN_EAST = 0x131 366 | BTN_B = BTN_EAST 367 | BTN_C = 0x132 368 | BTN_NORTH = 0x133 369 | BTN_X = BTN_NORTH 370 | BTN_WEST = 0x134 371 | BTN_Y = BTN_WEST 372 | BTN_Z = 0x135 373 | BTN_TL = 0x136 374 | BTN_TR = 0x137 375 | BTN_TL2 = 0x138 376 | BTN_TR2 = 0x139 377 | BTN_SELECT = 0x13a 378 | BTN_START = 0x13b 379 | BTN_MODE = 0x13c 380 | BTN_THUMBL = 0x13d 381 | BTN_THUMBR = 0x13e 382 | 383 | BTN_DIGI = 0x140 384 | BTN_TOOL_PEN = 0x140 385 | BTN_TOOL_RUBBER = 0x141 386 | BTN_TOOL_BRUSH = 0x142 387 | BTN_TOOL_PENCIL = 0x143 388 | BTN_TOOL_AIRBRUSH = 0x144 389 | BTN_TOOL_FINGER = 0x145 390 | BTN_TOOL_MOUSE = 0x146 391 | BTN_TOOL_LENS = 0x147 392 | BTN_TOOL_QUINTTAP = 0x148 // Five fingers on trackpad 393 | BTN_STYLUS3 = 0x149 394 | BTN_TOUCH = 0x14a 395 | BTN_STYLUS = 0x14b 396 | BTN_STYLUS2 = 0x14c 397 | BTN_TOOL_DOUBLETAP = 0x14d 398 | BTN_TOOL_TRIPLETAP = 0x14e 399 | BTN_TOOL_QUADTAP = 0x14f // Four fingers on trackpad 400 | 401 | BTN_WHEEL = 0x150 402 | BTN_GEAR_DOWN = 0x150 403 | BTN_GEAR_UP = 0x151 404 | 405 | KEY_OK = 0x160 406 | KEY_SELECT = 0x161 407 | KEY_GOTO = 0x162 408 | KEY_CLEAR = 0x163 409 | KEY_POWER2 = 0x164 410 | KEY_OPTION = 0x165 411 | KEY_INFO = 0x166 // AL OEM Features/Tips/Tutorial 412 | KEY_TIME = 0x167 413 | KEY_VENDOR = 0x168 414 | KEY_ARCHIVE = 0x169 415 | KEY_PROGRAM = 0x16a // Media Select Program Guide 416 | KEY_CHANNEL = 0x16b 417 | KEY_FAVORITES = 0x16c 418 | KEY_EPG = 0x16d 419 | KEY_PVR = 0x16e // Media Select Home 420 | KEY_MHP = 0x16f 421 | KEY_LANGUAGE = 0x170 422 | KEY_TITLE = 0x171 423 | KEY_SUBTITLE = 0x172 424 | KEY_ANGLE = 0x173 425 | KEY_FULL_SCREEN = 0x174 // AC View Toggle 426 | KEY_ZOOM = KEY_FULL_SCREEN 427 | KEY_MODE = 0x175 428 | KEY_KEYBOARD = 0x176 429 | KEY_ASPECT_RATIO = 0x177 // HUTRR37: Aspect 430 | KEY_SCREEN = KEY_ASPECT_RATIO 431 | KEY_PC = 0x178 // Media Select Computer 432 | KEY_TV = 0x179 // Media Select TV 433 | KEY_TV2 = 0x17a // Media Select Cable 434 | KEY_VCR = 0x17b // Media Select VCR 435 | KEY_VCR2 = 0x17c // VCR Plus 436 | KEY_SAT = 0x17d // Media Select Satellite 437 | KEY_SAT2 = 0x17e 438 | KEY_CD = 0x17f // Media Select CD 439 | KEY_TAPE = 0x180 // Media Select Tape 440 | KEY_RADIO = 0x181 441 | KEY_TUNER = 0x182 // Media Select Tuner 442 | KEY_PLAYER = 0x183 443 | KEY_TEXT = 0x184 444 | KEY_DVD = 0x185 // Media Select DVD 445 | KEY_AUX = 0x186 446 | KEY_MP3 = 0x187 447 | KEY_AUDIO = 0x188 // AL Audio Browser 448 | KEY_VIDEO = 0x189 // AL Movie Browser 449 | KEY_DIRECTORY = 0x18a 450 | KEY_LIST = 0x18b 451 | KEY_MEMO = 0x18c // Media Select Messages 452 | KEY_CALENDAR = 0x18d 453 | KEY_RED = 0x18e 454 | KEY_GREEN = 0x18f 455 | KEY_YELLOW = 0x190 456 | KEY_BLUE = 0x191 457 | KEY_CHANNELUP = 0x192 // Channel Increment 458 | KEY_CHANNELDOWN = 0x193 // Channel Decrement 459 | KEY_FIRST = 0x194 460 | KEY_LAST = 0x195 // Recall Last 461 | KEY_AB = 0x196 462 | KEY_NEXT = 0x197 463 | KEY_RESTART = 0x198 464 | KEY_SLOW = 0x199 465 | KEY_SHUFFLE = 0x19a 466 | KEY_BREAK = 0x19b 467 | KEY_PREVIOUS = 0x19c 468 | KEY_DIGITS = 0x19d 469 | KEY_TEEN = 0x19e 470 | KEY_TWEN = 0x19f 471 | KEY_VIDEOPHONE = 0x1a0 // Media Select Video Phone 472 | KEY_GAMES = 0x1a1 // Media Select Games 473 | KEY_ZOOMIN = 0x1a2 // AC Zoom In 474 | KEY_ZOOMOUT = 0x1a3 // AC Zoom Out 475 | KEY_ZOOMRESET = 0x1a4 // AC Zoom 476 | KEY_WORDPROCESSOR = 0x1a5 // AL Word Processor 477 | KEY_EDITOR = 0x1a6 // AL Text Editor 478 | KEY_SPREADSHEET = 0x1a7 // AL Spreadsheet 479 | KEY_GRAPHICSEDITOR = 0x1a8 // AL Graphics Editor 480 | KEY_PRESENTATION = 0x1a9 // AL Presentation App 481 | KEY_DATABASE = 0x1aa // AL Database App 482 | KEY_NEWS = 0x1ab // AL Newsreader 483 | KEY_VOICEMAIL = 0x1ac // AL Voicemail 484 | KEY_ADDRESSBOOK = 0x1ad // AL Contacts/Address Book 485 | KEY_MESSENGER = 0x1ae // AL Instant Messaging 486 | KEY_DISPLAYTOGGLE = 0x1af // Turn display (LCD) on and off 487 | KEY_BRIGHTNESS_TOGGLE = KEY_DISPLAYTOGGLE 488 | KEY_SPELLCHECK = 0x1b0 // AL Spell Check 489 | KEY_LOGOFF = 0x1b1 // AL Logoff 490 | 491 | KEY_DOLLAR = 0x1b2 492 | KEY_EURO = 0x1b3 493 | 494 | KEY_FRAMEBACK = 0x1b4 // Consumer - transport controls 495 | KEY_FRAMEFORWARD = 0x1b5 496 | KEY_CONTEXT_MENU = 0x1b6 // GenDesc - system context menu 497 | KEY_MEDIA_REPEAT = 0x1b7 // Consumer - transport control 498 | KEY_10CHANNELSUP = 0x1b8 // 10 channels up (10+) 499 | KEY_10CHANNELSDOWN = 0x1b9 // 10 channels down (10-) 500 | KEY_IMAGES = 0x1ba // AL Image Browser 501 | KEY_NOTIFICATION_CENTER = 0x1bc // Show/hide the notification center 502 | KEY_PICKUP_PHONE = 0x1bd // Answer incoming call 503 | KEY_HANGUP_PHONE = 0x1be // Decline incoming call 504 | 505 | KEY_DEL_EOL = 0x1c0 506 | KEY_DEL_EOS = 0x1c1 507 | KEY_INS_LINE = 0x1c2 508 | KEY_DEL_LINE = 0x1c3 509 | 510 | KEY_FN = 0x1d0 511 | KEY_FN_ESC = 0x1d1 512 | KEY_FN_F1 = 0x1d2 513 | KEY_FN_F2 = 0x1d3 514 | KEY_FN_F3 = 0x1d4 515 | KEY_FN_F4 = 0x1d5 516 | KEY_FN_F5 = 0x1d6 517 | KEY_FN_F6 = 0x1d7 518 | KEY_FN_F7 = 0x1d8 519 | KEY_FN_F8 = 0x1d9 520 | KEY_FN_F9 = 0x1da 521 | KEY_FN_F10 = 0x1db 522 | KEY_FN_F11 = 0x1dc 523 | KEY_FN_F12 = 0x1dd 524 | KEY_FN_1 = 0x1de 525 | KEY_FN_2 = 0x1df 526 | KEY_FN_D = 0x1e0 527 | KEY_FN_E = 0x1e1 528 | KEY_FN_F = 0x1e2 529 | KEY_FN_S = 0x1e3 530 | KEY_FN_B = 0x1e4 531 | KEY_FN_RIGHT_SHIFT = 0x1e5 532 | 533 | KEY_BRL_DOT1 = 0x1f1 534 | KEY_BRL_DOT2 = 0x1f2 535 | KEY_BRL_DOT3 = 0x1f3 536 | KEY_BRL_DOT4 = 0x1f4 537 | KEY_BRL_DOT5 = 0x1f5 538 | KEY_BRL_DOT6 = 0x1f6 539 | KEY_BRL_DOT7 = 0x1f7 540 | KEY_BRL_DOT8 = 0x1f8 541 | KEY_BRL_DOT9 = 0x1f9 542 | KEY_BRL_DOT10 = 0x1fa 543 | 544 | KEY_NUMERIC_0 = 0x200 // used by phones, remote controls, 545 | KEY_NUMERIC_1 = 0x201 // and other keypads 546 | KEY_NUMERIC_2 = 0x202 547 | KEY_NUMERIC_3 = 0x203 548 | KEY_NUMERIC_4 = 0x204 549 | KEY_NUMERIC_5 = 0x205 550 | KEY_NUMERIC_6 = 0x206 551 | KEY_NUMERIC_7 = 0x207 552 | KEY_NUMERIC_8 = 0x208 553 | KEY_NUMERIC_9 = 0x209 554 | KEY_NUMERIC_STAR = 0x20a 555 | KEY_NUMERIC_POUND = 0x20b 556 | KEY_NUMERIC_A = 0x20c // Phone key A - HUT Telephony 0xb9 557 | KEY_NUMERIC_B = 0x20d 558 | KEY_NUMERIC_C = 0x20e 559 | KEY_NUMERIC_D = 0x20f 560 | 561 | KEY_CAMERA_FOCUS = 0x210 562 | KEY_WPS_BUTTON = 0x211 // WiFi Protected Setup key 563 | 564 | KEY_TOUCHPAD_TOGGLE = 0x212 // Request switch touchpad on or off 565 | KEY_TOUCHPAD_ON = 0x213 566 | KEY_TOUCHPAD_OFF = 0x214 567 | 568 | KEY_CAMERA_ZOOMIN = 0x215 569 | KEY_CAMERA_ZOOMOUT = 0x216 570 | KEY_CAMERA_UP = 0x217 571 | KEY_CAMERA_DOWN = 0x218 572 | KEY_CAMERA_LEFT = 0x219 573 | KEY_CAMERA_RIGHT = 0x21a 574 | 575 | KEY_ATTENDANT_ON = 0x21b 576 | KEY_ATTENDANT_OFF = 0x21c 577 | KEY_ATTENDANT_TOGGLE = 0x21d // Attendant call on or off 578 | KEY_LIGHTS_TOGGLE = 0x21e // Reading light on or off 579 | 580 | BTN_DPAD_UP = 0x220 581 | BTN_DPAD_DOWN = 0x221 582 | BTN_DPAD_LEFT = 0x222 583 | BTN_DPAD_RIGHT = 0x223 584 | 585 | KEY_ALS_TOGGLE = 0x230 // Ambient light sensor 586 | KEY_ROTATE_LOCK_TOGGLE = 0x231 // Display rotation lock 587 | 588 | KEY_BUTTONCONFIG = 0x240 // AL Button Configuration 589 | KEY_TASKMANAGER = 0x241 // AL Task/Project Manager 590 | KEY_JOURNAL = 0x242 // AL Log/Journal/Timecard 591 | KEY_CONTROLPANEL = 0x243 // AL Control Panel 592 | KEY_APPSELECT = 0x244 // AL Select Task/Application 593 | KEY_SCREENSAVER = 0x245 // AL Screen Saver 594 | KEY_VOICECOMMAND = 0x246 // Listening Voice Command 595 | KEY_ASSISTANT = 0x247 // AL Context-aware desktop assistant 596 | KEY_KBD_LAYOUT_NEXT = 0x248 // AC Next Keyboard Layout Select 597 | KEY_EMOJI_PICKER = 0x249 // Show/hide emoji picker (HUTRR101) 598 | KEY_DICTATE = 0x24a // Start or Stop Voice Dictation Session (HUTRR99) 599 | KEY_CAMERA_ACCESS_ENABLE = 0x24b // Enables programmatic access to camera devices. (HUTRR72) 600 | KEY_CAMERA_ACCESS_DISABLE = 0x24c // Disables programmatic access to camera devices. (HUTRR72) 601 | KEY_CAMERA_ACCESS_TOGGLE = 0x24d // Toggles the current state of the camera access control. (HUTRR72) 602 | 603 | KEY_BRIGHTNESS_MIN = 0x250 // Set Brightness to Minimum 604 | KEY_BRIGHTNESS_MAX = 0x251 // Set Brightness to Maximum 605 | 606 | KEY_KBDINPUTASSIST_PREV = 0x260 607 | KEY_KBDINPUTASSIST_NEXT = 0x261 608 | KEY_KBDINPUTASSIST_PREVGROUP = 0x262 609 | KEY_KBDINPUTASSIST_NEXTGROUP = 0x263 610 | KEY_KBDINPUTASSIST_ACCEPT = 0x264 611 | KEY_KBDINPUTASSIST_CANCEL = 0x265 612 | 613 | // Diagonal movement keys 614 | 615 | KEY_RIGHT_UP = 0x266 616 | KEY_RIGHT_DOWN = 0x267 617 | KEY_LEFT_UP = 0x268 618 | KEY_LEFT_DOWN = 0x269 619 | 620 | KEY_ROOT_MENU = 0x26a // Show Device's Root Menu 621 | // Show Top Menu of the Media (e.g. DVD) 622 | 623 | KEY_MEDIA_TOP_MENU = 0x26b 624 | KEY_NUMERIC_11 = 0x26c 625 | KEY_NUMERIC_12 = 0x26d 626 | // Toggle Audio Description: refers to an audio service that helps blind and 627 | // visually impaired consumers understand the action in a program. Note: in 628 | // some countries this is referred to as "Video Description". 629 | 630 | KEY_AUDIO_DESC = 0x26e 631 | KEY_3D_MODE = 0x26f 632 | KEY_NEXT_FAVORITE = 0x270 633 | KEY_STOP_RECORD = 0x271 634 | KEY_PAUSE_RECORD = 0x272 635 | KEY_VOD = 0x273 // Video on Demand 636 | KEY_UNMUTE = 0x274 637 | KEY_FASTREVERSE = 0x275 638 | KEY_SLOWREVERSE = 0x276 639 | // Control a data application associated with the currently viewed channel, 640 | // e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.) 641 | 642 | KEY_DATA = 0x277 643 | KEY_ONSCREEN_KEYBOARD = 0x278 644 | // Electronic privacy screen control 645 | 646 | KEY_PRIVACY_SCREEN_TOGGLE = 0x279 647 | 648 | // Select an area of screen to be copied 649 | 650 | KEY_SELECTIVE_SCREENSHOT = 0x27a 651 | 652 | // Move the focus to the next or previous user controllable element within a UI container 653 | 654 | KEY_NEXT_ELEMENT = 0x27b 655 | KEY_PREVIOUS_ELEMENT = 0x27c 656 | 657 | // Toggle Autopilot engagement 658 | 659 | KEY_AUTOPILOT_ENGAGE_TOGGLE = 0x27d 660 | 661 | // Shortcut Keys 662 | 663 | KEY_MARK_WAYPOINT = 0x27e 664 | KEY_SOS = 0x27f 665 | KEY_NAV_CHART = 0x280 666 | KEY_FISHING_CHART = 0x281 667 | KEY_SINGLE_RANGE_RADAR = 0x282 668 | KEY_DUAL_RANGE_RADAR = 0x283 669 | KEY_RADAR_OVERLAY = 0x284 670 | KEY_TRADITIONAL_SONAR = 0x285 671 | KEY_CLEARVU_SONAR = 0x286 672 | KEY_SIDEVU_SONAR = 0x287 673 | KEY_NAV_INFO = 0x288 674 | KEY_BRIGHTNESS_MENU = 0x289 675 | 676 | // Some keyboards have keys which do not have a defined meaning, these keys 677 | // are intended to be programmed / bound to macros by the user. For most 678 | // keyboards with these macro-keys the key-sequence to inject, or action to 679 | // take, is all handled by software on the host side. So from the kernel's 680 | // point of view these are just normal keys. 681 | // The KEY_MACRO# codes below are intended for such keys, which may be labeled 682 | // e.g. G1-G18, or S1 - S30. The KEY_MACRO# codes MUST NOT be used for keys 683 | // where the marking on the key does indicate a defined meaning / purpose. 684 | // The KEY_MACRO# codes MUST also NOT be used as fallback for when no existing 685 | // KEY_FOO define matches the marking / purpose. In this case a new KEY_FOO 686 | // define MUST be added. 687 | 688 | KEY_MACRO1 = 0x290 689 | KEY_MACRO2 = 0x291 690 | KEY_MACRO3 = 0x292 691 | KEY_MACRO4 = 0x293 692 | KEY_MACRO5 = 0x294 693 | KEY_MACRO6 = 0x295 694 | KEY_MACRO7 = 0x296 695 | KEY_MACRO8 = 0x297 696 | KEY_MACRO9 = 0x298 697 | KEY_MACRO10 = 0x299 698 | KEY_MACRO11 = 0x29a 699 | KEY_MACRO12 = 0x29b 700 | KEY_MACRO13 = 0x29c 701 | KEY_MACRO14 = 0x29d 702 | KEY_MACRO15 = 0x29e 703 | KEY_MACRO16 = 0x29f 704 | KEY_MACRO17 = 0x2a0 705 | KEY_MACRO18 = 0x2a1 706 | KEY_MACRO19 = 0x2a2 707 | KEY_MACRO20 = 0x2a3 708 | KEY_MACRO21 = 0x2a4 709 | KEY_MACRO22 = 0x2a5 710 | KEY_MACRO23 = 0x2a6 711 | KEY_MACRO24 = 0x2a7 712 | KEY_MACRO25 = 0x2a8 713 | KEY_MACRO26 = 0x2a9 714 | KEY_MACRO27 = 0x2aa 715 | KEY_MACRO28 = 0x2ab 716 | KEY_MACRO29 = 0x2ac 717 | KEY_MACRO30 = 0x2ad 718 | 719 | // Some keyboards with the macro-keys described above have some extra keys 720 | // for controlling the host-side software responsible for the macro handling: 721 | // -A macro recording start/stop key. Note that not all keyboards which emit 722 | // KEY_MACRO_RECORD_START will also emit KEY_MACRO_RECORD_STOP if 723 | // KEY_MACRO_RECORD_STOP is not advertised, then KEY_MACRO_RECORD_START 724 | // should be interpreted as a recording start/stop toggle; 725 | // -Keys for switching between different macro (pre)sets, either a key for 726 | // cycling through the configured presets or keys to directly select a preset. 727 | 728 | KEY_MACRO_RECORD_START = 0x2b0 729 | KEY_MACRO_RECORD_STOP = 0x2b1 730 | KEY_MACRO_PRESET_CYCLE = 0x2b2 731 | KEY_MACRO_PRESET1 = 0x2b3 732 | KEY_MACRO_PRESET2 = 0x2b4 733 | KEY_MACRO_PRESET3 = 0x2b5 734 | 735 | // Some keyboards have a buildin LCD panel where the contents are controlled 736 | // by the host. Often these have a number of keys directly below the LCD 737 | // intended for controlling a menu shown on the LCD. These keys often don't 738 | // have any labeling so we just name them KEY_KBD_LCD_MENU# 739 | 740 | KEY_KBD_LCD_MENU1 = 0x2b8 741 | KEY_KBD_LCD_MENU2 = 0x2b9 742 | KEY_KBD_LCD_MENU3 = 0x2ba 743 | KEY_KBD_LCD_MENU4 = 0x2bb 744 | KEY_KBD_LCD_MENU5 = 0x2bc 745 | 746 | BTN_TRIGGER_HAPPY = 0x2c0 747 | BTN_TRIGGER_HAPPY1 = 0x2c0 748 | BTN_TRIGGER_HAPPY2 = 0x2c1 749 | BTN_TRIGGER_HAPPY3 = 0x2c2 750 | BTN_TRIGGER_HAPPY4 = 0x2c3 751 | BTN_TRIGGER_HAPPY5 = 0x2c4 752 | BTN_TRIGGER_HAPPY6 = 0x2c5 753 | BTN_TRIGGER_HAPPY7 = 0x2c6 754 | BTN_TRIGGER_HAPPY8 = 0x2c7 755 | BTN_TRIGGER_HAPPY9 = 0x2c8 756 | BTN_TRIGGER_HAPPY10 = 0x2c9 757 | BTN_TRIGGER_HAPPY11 = 0x2ca 758 | BTN_TRIGGER_HAPPY12 = 0x2cb 759 | BTN_TRIGGER_HAPPY13 = 0x2cc 760 | BTN_TRIGGER_HAPPY14 = 0x2cd 761 | BTN_TRIGGER_HAPPY15 = 0x2ce 762 | BTN_TRIGGER_HAPPY16 = 0x2cf 763 | BTN_TRIGGER_HAPPY17 = 0x2d0 764 | BTN_TRIGGER_HAPPY18 = 0x2d1 765 | BTN_TRIGGER_HAPPY19 = 0x2d2 766 | BTN_TRIGGER_HAPPY20 = 0x2d3 767 | BTN_TRIGGER_HAPPY21 = 0x2d4 768 | BTN_TRIGGER_HAPPY22 = 0x2d5 769 | BTN_TRIGGER_HAPPY23 = 0x2d6 770 | BTN_TRIGGER_HAPPY24 = 0x2d7 771 | BTN_TRIGGER_HAPPY25 = 0x2d8 772 | BTN_TRIGGER_HAPPY26 = 0x2d9 773 | BTN_TRIGGER_HAPPY27 = 0x2da 774 | BTN_TRIGGER_HAPPY28 = 0x2db 775 | BTN_TRIGGER_HAPPY29 = 0x2dc 776 | BTN_TRIGGER_HAPPY30 = 0x2dd 777 | BTN_TRIGGER_HAPPY31 = 0x2de 778 | BTN_TRIGGER_HAPPY32 = 0x2df 779 | BTN_TRIGGER_HAPPY33 = 0x2e0 780 | BTN_TRIGGER_HAPPY34 = 0x2e1 781 | BTN_TRIGGER_HAPPY35 = 0x2e2 782 | BTN_TRIGGER_HAPPY36 = 0x2e3 783 | BTN_TRIGGER_HAPPY37 = 0x2e4 784 | BTN_TRIGGER_HAPPY38 = 0x2e5 785 | BTN_TRIGGER_HAPPY39 = 0x2e6 786 | BTN_TRIGGER_HAPPY40 = 0x2e7 787 | 788 | // We avoid low common keys in module aliases so they don't get huge. 789 | 790 | KEY_MIN_INTERESTING = KEY_MUTE 791 | KEY_MAX = 0x2ff 792 | KEY_CNT = (KEY_MAX + 1) 793 | ) 794 | 795 | // Relative axes 796 | const ( 797 | REL_X = 0x00 798 | REL_Y = 0x01 799 | REL_Z = 0x02 800 | REL_RX = 0x03 801 | REL_RY = 0x04 802 | REL_RZ = 0x05 803 | REL_HWHEEL = 0x06 804 | REL_DIAL = 0x07 805 | REL_WHEEL = 0x08 806 | REL_MISC = 0x09 807 | // 0x0a is reserved and should not be used in input drivers. 808 | // It was used by HID as REL_MISC+1 and userspace needs to detect if 809 | // the next REL_* event is correct or is just REL_MISC + n. 810 | // We define here REL_RESERVED so userspace can rely on it and detect 811 | // the situation described above. 812 | 813 | REL_RESERVED = 0x0a 814 | REL_WHEEL_HI_RES = 0x0b 815 | REL_HWHEEL_HI_RES = 0x0c 816 | REL_MAX = 0x0f 817 | REL_CNT = (REL_MAX + 1) 818 | ) 819 | 820 | // Absolute axes 821 | const ( 822 | ABS_X = 0x00 823 | ABS_Y = 0x01 824 | ABS_Z = 0x02 825 | ABS_RX = 0x03 826 | ABS_RY = 0x04 827 | ABS_RZ = 0x05 828 | ABS_THROTTLE = 0x06 829 | ABS_RUDDER = 0x07 830 | ABS_WHEEL = 0x08 831 | ABS_GAS = 0x09 832 | ABS_BRAKE = 0x0a 833 | ABS_HAT0X = 0x10 834 | ABS_HAT0Y = 0x11 835 | ABS_HAT1X = 0x12 836 | ABS_HAT1Y = 0x13 837 | ABS_HAT2X = 0x14 838 | ABS_HAT2Y = 0x15 839 | ABS_HAT3X = 0x16 840 | ABS_HAT3Y = 0x17 841 | ABS_PRESSURE = 0x18 842 | ABS_DISTANCE = 0x19 843 | ABS_TILT_X = 0x1a 844 | ABS_TILT_Y = 0x1b 845 | ABS_TOOL_WIDTH = 0x1c 846 | 847 | ABS_VOLUME = 0x20 848 | ABS_PROFILE = 0x21 849 | 850 | ABS_MISC = 0x28 851 | 852 | // 0x2e is reserved and should not be used in input drivers. 853 | // It was used by HID as ABS_MISC+6 and userspace needs to detect if 854 | // the next ABS_* event is correct or is just ABS_MISC + n. 855 | // We define here ABS_RESERVED so userspace can rely on it and detect 856 | // the situation described above. 857 | 858 | ABS_RESERVED = 0x2e 859 | 860 | ABS_MT_SLOT = 0x2f // MT slot being modified 861 | ABS_MT_TOUCH_MAJOR = 0x30 // Major axis of touching ellipse 862 | ABS_MT_TOUCH_MINOR = 0x31 // Minor axis (omit if circular) 863 | ABS_MT_WIDTH_MAJOR = 0x32 // Major axis of approaching ellipse 864 | ABS_MT_WIDTH_MINOR = 0x33 // Minor axis (omit if circular) 865 | ABS_MT_ORIENTATION = 0x34 // Ellipse orientation 866 | ABS_MT_POSITION_X = 0x35 // Center X touch position 867 | ABS_MT_POSITION_Y = 0x36 // Center Y touch position 868 | ABS_MT_TOOL_TYPE = 0x37 // Type of touching device 869 | ABS_MT_BLOB_ID = 0x38 // Group a set of packets as a blob 870 | ABS_MT_TRACKING_ID = 0x39 // Unique ID of initiated contact 871 | ABS_MT_PRESSURE = 0x3a // Pressure on contact area 872 | ABS_MT_DISTANCE = 0x3b // Contact hover distance 873 | ABS_MT_TOOL_X = 0x3c // Center X tool position 874 | ABS_MT_TOOL_Y = 0x3d // Center Y tool position 875 | 876 | ABS_MAX = 0x3f 877 | ABS_CNT = (ABS_MAX + 1) 878 | ) 879 | 880 | // Switch events 881 | const ( 882 | SW_LID = 0x00 // set = lid shut 883 | SW_TABLET_MODE = 0x01 // set = tablet mode 884 | SW_HEADPHONE_INSERT = 0x02 // set = inserted 885 | SW_RFKILL_ALL = 0x03 // rfkill master switch, type "any"set = radio enabled 886 | 887 | SW_RADIO = SW_RFKILL_ALL // deprecated 888 | SW_MICROPHONE_INSERT = 0x04 // set = inserted 889 | SW_DOCK = 0x05 // set = plugged into dock 890 | SW_LINEOUT_INSERT = 0x06 // set = inserted 891 | SW_JACK_PHYSICAL_INSERT = 0x07 // set = mechanical switch set 892 | SW_VIDEOOUT_INSERT = 0x08 // set = inserted 893 | SW_CAMERA_LENS_COVER = 0x09 // set = lens covered 894 | SW_KEYPAD_SLIDE = 0x0a // set = keypad slide out 895 | SW_FRONT_PROXIMITY = 0x0b // set = front proximity sensor active 896 | SW_ROTATE_LOCK = 0x0c // set = rotate locked/disabled 897 | SW_LINEIN_INSERT = 0x0d // set = inserted 898 | SW_MUTE_DEVICE = 0x0e // set = device disabled 899 | SW_PEN_INSERTED = 0x0f // set = pen inserted 900 | SW_MACHINE_COVER = 0x10 // set = cover closed 901 | SW_MAX = 0x10 902 | SW_CNT = (SW_MAX + 1) 903 | ) 904 | 905 | // Misc events 906 | const ( 907 | MSC_SERIAL = 0x00 908 | MSC_PULSELED = 0x01 909 | MSC_GESTURE = 0x02 910 | MSC_RAW = 0x03 911 | MSC_SCAN = 0x04 912 | MSC_TIMESTAMP = 0x05 913 | MSC_MAX = 0x07 914 | MSC_CNT = (MSC_MAX + 1) 915 | ) 916 | 917 | // LEDs 918 | const ( 919 | LED_NUML = 0x00 920 | LED_CAPSL = 0x01 921 | LED_SCROLLL = 0x02 922 | LED_COMPOSE = 0x03 923 | LED_KANA = 0x04 924 | LED_SLEEP = 0x05 925 | LED_SUSPEND = 0x06 926 | LED_MUTE = 0x07 927 | LED_MISC = 0x08 928 | LED_MAIL = 0x09 929 | LED_CHARGING = 0x0a 930 | LED_MAX = 0x0f 931 | LED_CNT = (LED_MAX + 1) 932 | ) 933 | 934 | // Autorepeat values 935 | const ( 936 | REP_DELAY = 0x00 937 | REP_PERIOD = 0x01 938 | REP_MAX = 0x01 939 | REP_CNT = (REP_MAX + 1) 940 | ) 941 | 942 | // Sounds 943 | const ( 944 | SND_CLICK = 0x00 945 | SND_BELL = 0x01 946 | SND_TONE = 0x02 947 | SND_MAX = 0x07 948 | SND_CNT = (SND_MAX + 1) 949 | ) 950 | 951 | // IDs. 952 | const ( 953 | ID_BUS = 0 954 | ID_VENDOR = 1 955 | ID_PRODUCT = 2 956 | ID_VERSION = 3 957 | ) 958 | 959 | const ( 960 | BUS_PCI = 0x01 961 | BUS_ISAPNP = 0x02 962 | BUS_USB = 0x03 963 | BUS_HIL = 0x04 964 | BUS_BLUETOOTH = 0x05 965 | BUS_VIRTUAL = 0x06 966 | 967 | BUS_ISA = 0x10 968 | BUS_I8042 = 0x11 969 | BUS_XTKBD = 0x12 970 | BUS_RS232 = 0x13 971 | BUS_GAMEPORT = 0x14 972 | BUS_PARPORT = 0x15 973 | BUS_AMIGA = 0x16 974 | BUS_ADB = 0x17 975 | BUS_I2C = 0x18 976 | BUS_HOST = 0x19 977 | BUS_GSC = 0x1A 978 | BUS_ATARI = 0x1B 979 | BUS_SPI = 0x1C 980 | BUS_RMI = 0x1D 981 | BUS_CEC = 0x1E 982 | BUS_INTEL_ISHTP = 0x1F 983 | BUS_AMD_SFH = 0x20 984 | ) 985 | 986 | // MT_TOOL types 987 | const ( 988 | MT_TOOL_FINGER = 0x00 989 | MT_TOOL_PEN = 0x01 990 | MT_TOOL_PALM = 0x02 991 | MT_TOOL_DIAL = 0x0a 992 | MT_TOOL_MAX = 0x0f 993 | ) 994 | 995 | // Values describing the status of a force-feedback effect 996 | const ( 997 | FF_STATUS_STOPPED = 0x00 998 | FF_STATUS_PLAYING = 0x01 999 | FF_STATUS_MAX = 0x01 1000 | 1001 | // Force feedback effect types 1002 | 1003 | FF_RUMBLE = 0x50 1004 | FF_PERIODIC = 0x51 1005 | FF_CONSTANT = 0x52 1006 | FF_SPRING = 0x53 1007 | FF_FRICTION = 0x54 1008 | FF_DAMPER = 0x55 1009 | FF_INERTIA = 0x56 1010 | FF_RAMP = 0x57 1011 | 1012 | FF_EFFECT_MIN = FF_RUMBLE 1013 | FF_EFFECT_MAX = FF_RAMP 1014 | 1015 | // Force feedback periodic effect types 1016 | 1017 | FF_SQUARE = 0x58 1018 | FF_TRIANGLE = 0x59 1019 | FF_SINE = 0x5a 1020 | FF_SAW_UP = 0x5b 1021 | FF_SAW_DOWN = 0x5c 1022 | FF_CUSTOM = 0x5d 1023 | 1024 | FF_WAVEFORM_MIN = FF_SQUARE 1025 | FF_WAVEFORM_MAX = FF_CUSTOM 1026 | 1027 | // Set ff device properties 1028 | 1029 | FF_GAIN = 0x60 1030 | FF_AUTOCENTER = 0x61 1031 | 1032 | // ff->playback(effect_id = FF_GAIN) is the first effect_id to 1033 | // cause a collision with another ff method, in this case ff->set_gain(). 1034 | // Therefore the greatest safe value for effect_id is FF_GAIN - 1, 1035 | // and thus the total number of effects should never exceed FF_GAIN. 1036 | 1037 | FF_MAX_EFFECTS = FF_GAIN 1038 | 1039 | FF_MAX = 0x7f 1040 | FF_CNT = (FF_MAX + 1) 1041 | ) 1042 | 1043 | // 1044 | // Type to String 1045 | // 1046 | 1047 | var INPUTToString = map[EvProp]string{ 1048 | INPUT_PROP_POINTER: "INPUT_PROP_POINTER", 1049 | INPUT_PROP_DIRECT: "INPUT_PROP_DIRECT", 1050 | INPUT_PROP_BUTTONPAD: "INPUT_PROP_BUTTONPAD", 1051 | INPUT_PROP_SEMI_MT: "INPUT_PROP_SEMI_MT", 1052 | INPUT_PROP_TOPBUTTONPAD: "INPUT_PROP_TOPBUTTONPAD", 1053 | INPUT_PROP_POINTING_STICK: "INPUT_PROP_POINTING_STICK", 1054 | INPUT_PROP_ACCELEROMETER: "INPUT_PROP_ACCELEROMETER", 1055 | 1056 | INPUT_PROP_MAX: "INPUT_PROP_MAX", 1057 | INPUT_PROP_CNT: "INPUT_PROP_CNT", 1058 | } 1059 | 1060 | var EVToString = map[EvType]string{ 1061 | EV_SYN: "EV_SYN", 1062 | EV_KEY: "EV_KEY", 1063 | EV_REL: "EV_REL", 1064 | EV_ABS: "EV_ABS", 1065 | EV_MSC: "EV_MSC", 1066 | EV_SW: "EV_SW", 1067 | EV_LED: "EV_LED", 1068 | EV_SND: "EV_SND", 1069 | EV_REP: "EV_REP", 1070 | EV_FF: "EV_FF", 1071 | EV_PWR: "EV_PWR", 1072 | EV_FF_STATUS: "EV_FF_STATUS", 1073 | EV_MAX: "EV_MAX", 1074 | EV_CNT: "EV_CNT", 1075 | } 1076 | 1077 | var SYNToString = map[EvCode]string{ 1078 | SYN_REPORT: "SYN_REPORT", 1079 | SYN_CONFIG: "SYN_CONFIG", 1080 | SYN_MT_REPORT: "SYN_MT_REPORT", 1081 | SYN_DROPPED: "SYN_DROPPED", 1082 | SYN_MAX: "SYN_MAX", 1083 | SYN_CNT: "SYN_CNT", 1084 | } 1085 | 1086 | var KEYToString = map[EvCode]string{ 1087 | KEY_RESERVED: "KEY_RESERVED", 1088 | KEY_ESC: "KEY_ESC", 1089 | KEY_1: "KEY_1", 1090 | KEY_2: "KEY_2", 1091 | KEY_3: "KEY_3", 1092 | KEY_4: "KEY_4", 1093 | KEY_5: "KEY_5", 1094 | KEY_6: "KEY_6", 1095 | KEY_7: "KEY_7", 1096 | KEY_8: "KEY_8", 1097 | KEY_9: "KEY_9", 1098 | KEY_0: "KEY_0", 1099 | KEY_MINUS: "KEY_MINUS", 1100 | KEY_EQUAL: "KEY_EQUAL", 1101 | KEY_BACKSPACE: "KEY_BACKSPACE", 1102 | KEY_TAB: "KEY_TAB", 1103 | KEY_Q: "KEY_Q", 1104 | KEY_W: "KEY_W", 1105 | KEY_E: "KEY_E", 1106 | KEY_R: "KEY_R", 1107 | KEY_T: "KEY_T", 1108 | KEY_Y: "KEY_Y", 1109 | KEY_U: "KEY_U", 1110 | KEY_I: "KEY_I", 1111 | KEY_O: "KEY_O", 1112 | KEY_P: "KEY_P", 1113 | KEY_LEFTBRACE: "KEY_LEFTBRACE", 1114 | KEY_RIGHTBRACE: "KEY_RIGHTBRACE", 1115 | KEY_ENTER: "KEY_ENTER", 1116 | KEY_LEFTCTRL: "KEY_LEFTCTRL", 1117 | KEY_A: "KEY_A", 1118 | KEY_S: "KEY_S", 1119 | KEY_D: "KEY_D", 1120 | KEY_F: "KEY_F", 1121 | KEY_G: "KEY_G", 1122 | KEY_H: "KEY_H", 1123 | KEY_J: "KEY_J", 1124 | KEY_K: "KEY_K", 1125 | KEY_L: "KEY_L", 1126 | KEY_SEMICOLON: "KEY_SEMICOLON", 1127 | KEY_APOSTROPHE: "KEY_APOSTROPHE", 1128 | KEY_GRAVE: "KEY_GRAVE", 1129 | KEY_LEFTSHIFT: "KEY_LEFTSHIFT", 1130 | KEY_BACKSLASH: "KEY_BACKSLASH", 1131 | KEY_Z: "KEY_Z", 1132 | KEY_X: "KEY_X", 1133 | KEY_C: "KEY_C", 1134 | KEY_V: "KEY_V", 1135 | KEY_B: "KEY_B", 1136 | KEY_N: "KEY_N", 1137 | KEY_M: "KEY_M", 1138 | KEY_COMMA: "KEY_COMMA", 1139 | KEY_DOT: "KEY_DOT", 1140 | KEY_SLASH: "KEY_SLASH", 1141 | KEY_RIGHTSHIFT: "KEY_RIGHTSHIFT", 1142 | KEY_KPASTERISK: "KEY_KPASTERISK", 1143 | KEY_LEFTALT: "KEY_LEFTALT", 1144 | KEY_SPACE: "KEY_SPACE", 1145 | KEY_CAPSLOCK: "KEY_CAPSLOCK", 1146 | KEY_F1: "KEY_F1", 1147 | KEY_F2: "KEY_F2", 1148 | KEY_F3: "KEY_F3", 1149 | KEY_F4: "KEY_F4", 1150 | KEY_F5: "KEY_F5", 1151 | KEY_F6: "KEY_F6", 1152 | KEY_F7: "KEY_F7", 1153 | KEY_F8: "KEY_F8", 1154 | KEY_F9: "KEY_F9", 1155 | KEY_F10: "KEY_F10", 1156 | KEY_NUMLOCK: "KEY_NUMLOCK", 1157 | KEY_SCROLLLOCK: "KEY_SCROLLLOCK", 1158 | KEY_KP7: "KEY_KP7", 1159 | KEY_KP8: "KEY_KP8", 1160 | KEY_KP9: "KEY_KP9", 1161 | KEY_KPMINUS: "KEY_KPMINUS", 1162 | KEY_KP4: "KEY_KP4", 1163 | KEY_KP5: "KEY_KP5", 1164 | KEY_KP6: "KEY_KP6", 1165 | KEY_KPPLUS: "KEY_KPPLUS", 1166 | KEY_KP1: "KEY_KP1", 1167 | KEY_KP2: "KEY_KP2", 1168 | KEY_KP3: "KEY_KP3", 1169 | KEY_KP0: "KEY_KP0", 1170 | KEY_KPDOT: "KEY_KPDOT", 1171 | 1172 | KEY_ZENKAKUHANKAKU: "KEY_ZENKAKUHANKAKU", 1173 | KEY_102ND: "KEY_102ND", 1174 | KEY_F11: "KEY_F11", 1175 | KEY_F12: "KEY_F12", 1176 | KEY_RO: "KEY_RO", 1177 | KEY_KATAKANA: "KEY_KATAKANA", 1178 | KEY_HIRAGANA: "KEY_HIRAGANA", 1179 | KEY_HENKAN: "KEY_HENKAN", 1180 | KEY_KATAKANAHIRAGANA: "KEY_KATAKANAHIRAGANA", 1181 | KEY_MUHENKAN: "KEY_MUHENKAN", 1182 | KEY_KPJPCOMMA: "KEY_KPJPCOMMA", 1183 | KEY_KPENTER: "KEY_KPENTER", 1184 | KEY_RIGHTCTRL: "KEY_RIGHTCTRL", 1185 | KEY_KPSLASH: "KEY_KPSLASH", 1186 | KEY_SYSRQ: "KEY_SYSRQ", 1187 | KEY_RIGHTALT: "KEY_RIGHTALT", 1188 | KEY_LINEFEED: "KEY_LINEFEED", 1189 | KEY_HOME: "KEY_HOME", 1190 | KEY_UP: "KEY_UP", 1191 | KEY_PAGEUP: "KEY_PAGEUP", 1192 | KEY_LEFT: "KEY_LEFT", 1193 | KEY_RIGHT: "KEY_RIGHT", 1194 | KEY_END: "KEY_END", 1195 | KEY_DOWN: "KEY_DOWN", 1196 | KEY_PAGEDOWN: "KEY_PAGEDOWN", 1197 | KEY_INSERT: "KEY_INSERT", 1198 | KEY_DELETE: "KEY_DELETE", 1199 | KEY_MACRO: "KEY_MACRO", 1200 | KEY_MUTE: "KEY_MUTE", 1201 | KEY_VOLUMEDOWN: "KEY_VOLUMEDOWN", 1202 | KEY_VOLUMEUP: "KEY_VOLUMEUP", 1203 | KEY_POWER: "KEY_POWER", 1204 | KEY_KPEQUAL: "KEY_KPEQUAL", 1205 | KEY_KPPLUSMINUS: "KEY_KPPLUSMINUS", 1206 | KEY_PAUSE: "KEY_PAUSE", 1207 | KEY_SCALE: "KEY_SCALE", 1208 | 1209 | KEY_KPCOMMA: "KEY_KPCOMMA", 1210 | KEY_HANGEUL: "KEY_HANGEUL", 1211 | // KEY_HANGUEL: "KEY_HANGUEL", // (KEY_HANGEUL) 1212 | KEY_HANJA: "KEY_HANJA", 1213 | KEY_YEN: "KEY_YEN", 1214 | KEY_LEFTMETA: "KEY_LEFTMETA", 1215 | KEY_RIGHTMETA: "KEY_RIGHTMETA", 1216 | KEY_COMPOSE: "KEY_COMPOSE", 1217 | 1218 | KEY_STOP: "KEY_STOP", 1219 | KEY_AGAIN: "KEY_AGAIN", 1220 | KEY_PROPS: "KEY_PROPS", 1221 | KEY_UNDO: "KEY_UNDO", 1222 | KEY_FRONT: "KEY_FRONT", 1223 | KEY_COPY: "KEY_COPY", 1224 | KEY_OPEN: "KEY_OPEN", 1225 | KEY_PASTE: "KEY_PASTE", 1226 | KEY_FIND: "KEY_FIND", 1227 | KEY_CUT: "KEY_CUT", 1228 | KEY_HELP: "KEY_HELP", 1229 | KEY_MENU: "KEY_MENU", 1230 | KEY_CALC: "KEY_CALC", 1231 | KEY_SETUP: "KEY_SETUP", 1232 | KEY_SLEEP: "KEY_SLEEP", 1233 | KEY_WAKEUP: "KEY_WAKEUP", 1234 | KEY_FILE: "KEY_FILE", 1235 | KEY_SENDFILE: "KEY_SENDFILE", 1236 | KEY_DELETEFILE: "KEY_DELETEFILE", 1237 | KEY_XFER: "KEY_XFER", 1238 | KEY_PROG1: "KEY_PROG1", 1239 | KEY_PROG2: "KEY_PROG2", 1240 | KEY_WWW: "KEY_WWW", 1241 | KEY_MSDOS: "KEY_MSDOS", 1242 | KEY_COFFEE: "KEY_COFFEE", 1243 | // KEY_SCREENLOCK: "KEY_SCREENLOCK", // (KEY_COFFEE) 1244 | KEY_ROTATE_DISPLAY: "KEY_ROTATE_DISPLAY", 1245 | // KEY_DIRECTION: "KEY_DIRECTION", // (KEY_ROTATE_DISPLAY) 1246 | KEY_CYCLEWINDOWS: "KEY_CYCLEWINDOWS", 1247 | KEY_MAIL: "KEY_MAIL", 1248 | KEY_BOOKMARKS: "KEY_BOOKMARKS", 1249 | KEY_COMPUTER: "KEY_COMPUTER", 1250 | KEY_BACK: "KEY_BACK", 1251 | KEY_FORWARD: "KEY_FORWARD", 1252 | KEY_CLOSECD: "KEY_CLOSECD", 1253 | KEY_EJECTCD: "KEY_EJECTCD", 1254 | KEY_EJECTCLOSECD: "KEY_EJECTCLOSECD", 1255 | KEY_NEXTSONG: "KEY_NEXTSONG", 1256 | KEY_PLAYPAUSE: "KEY_PLAYPAUSE", 1257 | KEY_PREVIOUSSONG: "KEY_PREVIOUSSONG", 1258 | KEY_STOPCD: "KEY_STOPCD", 1259 | KEY_RECORD: "KEY_RECORD", 1260 | KEY_REWIND: "KEY_REWIND", 1261 | KEY_PHONE: "KEY_PHONE", 1262 | KEY_ISO: "KEY_ISO", 1263 | KEY_CONFIG: "KEY_CONFIG", 1264 | KEY_HOMEPAGE: "KEY_HOMEPAGE", 1265 | KEY_REFRESH: "KEY_REFRESH", 1266 | KEY_EXIT: "KEY_EXIT", 1267 | KEY_MOVE: "KEY_MOVE", 1268 | KEY_EDIT: "KEY_EDIT", 1269 | KEY_SCROLLUP: "KEY_SCROLLUP", 1270 | KEY_SCROLLDOWN: "KEY_SCROLLDOWN", 1271 | KEY_KPLEFTPAREN: "KEY_KPLEFTPAREN", 1272 | KEY_KPRIGHTPAREN: "KEY_KPRIGHTPAREN", 1273 | KEY_NEW: "KEY_NEW", 1274 | KEY_REDO: "KEY_REDO", 1275 | 1276 | KEY_F13: "KEY_F13", 1277 | KEY_F14: "KEY_F14", 1278 | KEY_F15: "KEY_F15", 1279 | KEY_F16: "KEY_F16", 1280 | KEY_F17: "KEY_F17", 1281 | KEY_F18: "KEY_F18", 1282 | KEY_F19: "KEY_F19", 1283 | KEY_F20: "KEY_F20", 1284 | KEY_F21: "KEY_F21", 1285 | KEY_F22: "KEY_F22", 1286 | KEY_F23: "KEY_F23", 1287 | KEY_F24: "KEY_F24", 1288 | 1289 | KEY_PLAYCD: "KEY_PLAYCD", 1290 | KEY_PAUSECD: "KEY_PAUSECD", 1291 | KEY_PROG3: "KEY_PROG3", 1292 | KEY_PROG4: "KEY_PROG4", 1293 | KEY_ALL_APPLICATIONS: "KEY_ALL_APPLICATIONS", 1294 | // KEY_DASHBOARD: "KEY_DASHBOARD", // (KEY_ALL_APPLICATIONS) 1295 | KEY_SUSPEND: "KEY_SUSPEND", 1296 | KEY_CLOSE: "KEY_CLOSE", 1297 | KEY_PLAY: "KEY_PLAY", 1298 | KEY_FASTFORWARD: "KEY_FASTFORWARD", 1299 | KEY_BASSBOOST: "KEY_BASSBOOST", 1300 | KEY_PRINT: "KEY_PRINT", 1301 | KEY_HP: "KEY_HP", 1302 | KEY_CAMERA: "KEY_CAMERA", 1303 | KEY_SOUND: "KEY_SOUND", 1304 | KEY_QUESTION: "KEY_QUESTION", 1305 | KEY_EMAIL: "KEY_EMAIL", 1306 | KEY_CHAT: "KEY_CHAT", 1307 | KEY_SEARCH: "KEY_SEARCH", 1308 | KEY_CONNECT: "KEY_CONNECT", 1309 | KEY_FINANCE: "KEY_FINANCE", 1310 | KEY_SPORT: "KEY_SPORT", 1311 | KEY_SHOP: "KEY_SHOP", 1312 | KEY_ALTERASE: "KEY_ALTERASE", 1313 | KEY_CANCEL: "KEY_CANCEL", 1314 | KEY_BRIGHTNESSDOWN: "KEY_BRIGHTNESSDOWN", 1315 | KEY_BRIGHTNESSUP: "KEY_BRIGHTNESSUP", 1316 | KEY_MEDIA: "KEY_MEDIA", 1317 | 1318 | KEY_SWITCHVIDEOMODE: "KEY_SWITCHVIDEOMODE", 1319 | KEY_KBDILLUMTOGGLE: "KEY_KBDILLUMTOGGLE", 1320 | KEY_KBDILLUMDOWN: "KEY_KBDILLUMDOWN", 1321 | KEY_KBDILLUMUP: "KEY_KBDILLUMUP", 1322 | 1323 | KEY_SEND: "KEY_SEND", 1324 | KEY_REPLY: "KEY_REPLY", 1325 | KEY_FORWARDMAIL: "KEY_FORWARDMAIL", 1326 | KEY_SAVE: "KEY_SAVE", 1327 | KEY_DOCUMENTS: "KEY_DOCUMENTS", 1328 | 1329 | KEY_BATTERY: "KEY_BATTERY", 1330 | 1331 | KEY_BLUETOOTH: "KEY_BLUETOOTH", 1332 | KEY_WLAN: "KEY_WLAN", 1333 | KEY_UWB: "KEY_UWB", 1334 | 1335 | KEY_UNKNOWN: "KEY_UNKNOWN", 1336 | 1337 | KEY_VIDEO_NEXT: "KEY_VIDEO_NEXT", 1338 | KEY_VIDEO_PREV: "KEY_VIDEO_PREV", 1339 | KEY_BRIGHTNESS_CYCLE: "KEY_BRIGHTNESS_CYCLE", 1340 | KEY_BRIGHTNESS_AUTO: "KEY_BRIGHTNESS_AUTO", 1341 | // KEY_BRIGHTNESS_ZERO: "KEY_BRIGHTNESS_ZERO", // (KEY_BRIGHTNESS_AUTO) 1342 | KEY_DISPLAY_OFF: "KEY_DISPLAY_OFF", 1343 | 1344 | KEY_WWAN: "KEY_WWAN", 1345 | // KEY_WIMAX: "KEY_WIMAX", // (KEY_WWAN) 1346 | KEY_RFKILL: "KEY_RFKILL", 1347 | 1348 | KEY_MICMUTE: "KEY_MICMUTE", 1349 | 1350 | BTN_MISC: "BTN_MISC", 1351 | // BTN_0: "BTN_0", // (BTN_MISC) 1352 | BTN_1: "BTN_1", 1353 | BTN_2: "BTN_2", 1354 | BTN_3: "BTN_3", 1355 | BTN_4: "BTN_4", 1356 | BTN_5: "BTN_5", 1357 | BTN_6: "BTN_6", 1358 | BTN_7: "BTN_7", 1359 | BTN_8: "BTN_8", 1360 | BTN_9: "BTN_9", 1361 | 1362 | BTN_MOUSE: "BTN_MOUSE", 1363 | // BTN_LEFT: "BTN_LEFT", // (BTN_MOUSE) 1364 | BTN_RIGHT: "BTN_RIGHT", 1365 | BTN_MIDDLE: "BTN_MIDDLE", 1366 | BTN_SIDE: "BTN_SIDE", 1367 | BTN_EXTRA: "BTN_EXTRA", 1368 | BTN_FORWARD: "BTN_FORWARD", 1369 | BTN_BACK: "BTN_BACK", 1370 | BTN_TASK: "BTN_TASK", 1371 | 1372 | BTN_JOYSTICK: "BTN_JOYSTICK", 1373 | // BTN_TRIGGER: "BTN_TRIGGER", // (BTN_JOYSTICK) 1374 | BTN_THUMB: "BTN_THUMB", 1375 | BTN_THUMB2: "BTN_THUMB2", 1376 | BTN_TOP: "BTN_TOP", 1377 | BTN_TOP2: "BTN_TOP2", 1378 | BTN_PINKIE: "BTN_PINKIE", 1379 | BTN_BASE: "BTN_BASE", 1380 | BTN_BASE2: "BTN_BASE2", 1381 | BTN_BASE3: "BTN_BASE3", 1382 | BTN_BASE4: "BTN_BASE4", 1383 | BTN_BASE5: "BTN_BASE5", 1384 | BTN_BASE6: "BTN_BASE6", 1385 | BTN_DEAD: "BTN_DEAD", 1386 | 1387 | BTN_GAMEPAD: "BTN_GAMEPAD", 1388 | // BTN_SOUTH: "BTN_SOUTH", // (BTN_GAMEPAD) 1389 | // BTN_A: "BTN_A", // (BTN_GAMEPAD) 1390 | BTN_EAST: "BTN_EAST", 1391 | // BTN_B: "BTN_B", // (BTN_EAST) 1392 | BTN_C: "BTN_C", 1393 | BTN_NORTH: "BTN_NORTH", 1394 | // BTN_X: "BTN_X", // (BTN_NORTH) 1395 | BTN_WEST: "BTN_WEST", 1396 | // BTN_Y: "BTN_Y", // (BTN_WEST) 1397 | BTN_Z: "BTN_Z", 1398 | BTN_TL: "BTN_TL", 1399 | BTN_TR: "BTN_TR", 1400 | BTN_TL2: "BTN_TL2", 1401 | BTN_TR2: "BTN_TR2", 1402 | BTN_SELECT: "BTN_SELECT", 1403 | BTN_START: "BTN_START", 1404 | BTN_MODE: "BTN_MODE", 1405 | BTN_THUMBL: "BTN_THUMBL", 1406 | BTN_THUMBR: "BTN_THUMBR", 1407 | 1408 | BTN_DIGI: "BTN_DIGI", 1409 | // BTN_TOOL_PEN: "BTN_TOOL_PEN", // (BTN_DIGI) 1410 | BTN_TOOL_RUBBER: "BTN_TOOL_RUBBER", 1411 | BTN_TOOL_BRUSH: "BTN_TOOL_BRUSH", 1412 | BTN_TOOL_PENCIL: "BTN_TOOL_PENCIL", 1413 | BTN_TOOL_AIRBRUSH: "BTN_TOOL_AIRBRUSH", 1414 | BTN_TOOL_FINGER: "BTN_TOOL_FINGER", 1415 | BTN_TOOL_MOUSE: "BTN_TOOL_MOUSE", 1416 | BTN_TOOL_LENS: "BTN_TOOL_LENS", 1417 | BTN_TOOL_QUINTTAP: "BTN_TOOL_QUINTTAP", 1418 | BTN_STYLUS3: "BTN_STYLUS3", 1419 | BTN_TOUCH: "BTN_TOUCH", 1420 | BTN_STYLUS: "BTN_STYLUS", 1421 | BTN_STYLUS2: "BTN_STYLUS2", 1422 | BTN_TOOL_DOUBLETAP: "BTN_TOOL_DOUBLETAP", 1423 | BTN_TOOL_TRIPLETAP: "BTN_TOOL_TRIPLETAP", 1424 | BTN_TOOL_QUADTAP: "BTN_TOOL_QUADTAP", 1425 | 1426 | BTN_WHEEL: "BTN_WHEEL", 1427 | // BTN_GEAR_DOWN: "BTN_GEAR_DOWN", // (BTN_WHEEL) 1428 | BTN_GEAR_UP: "BTN_GEAR_UP", 1429 | 1430 | KEY_OK: "KEY_OK", 1431 | KEY_SELECT: "KEY_SELECT", 1432 | KEY_GOTO: "KEY_GOTO", 1433 | KEY_CLEAR: "KEY_CLEAR", 1434 | KEY_POWER2: "KEY_POWER2", 1435 | KEY_OPTION: "KEY_OPTION", 1436 | KEY_INFO: "KEY_INFO", 1437 | KEY_TIME: "KEY_TIME", 1438 | KEY_VENDOR: "KEY_VENDOR", 1439 | KEY_ARCHIVE: "KEY_ARCHIVE", 1440 | KEY_PROGRAM: "KEY_PROGRAM", 1441 | KEY_CHANNEL: "KEY_CHANNEL", 1442 | KEY_FAVORITES: "KEY_FAVORITES", 1443 | KEY_EPG: "KEY_EPG", 1444 | KEY_PVR: "KEY_PVR", 1445 | KEY_MHP: "KEY_MHP", 1446 | KEY_LANGUAGE: "KEY_LANGUAGE", 1447 | KEY_TITLE: "KEY_TITLE", 1448 | KEY_SUBTITLE: "KEY_SUBTITLE", 1449 | KEY_ANGLE: "KEY_ANGLE", 1450 | KEY_FULL_SCREEN: "KEY_FULL_SCREEN", 1451 | // KEY_ZOOM: "KEY_ZOOM", // (KEY_FULL_SCREEN) 1452 | KEY_MODE: "KEY_MODE", 1453 | KEY_KEYBOARD: "KEY_KEYBOARD", 1454 | KEY_ASPECT_RATIO: "KEY_ASPECT_RATIO", 1455 | // KEY_SCREEN: "KEY_SCREEN", // (KEY_ASPECT_RATIO) 1456 | KEY_PC: "KEY_PC", 1457 | KEY_TV: "KEY_TV", 1458 | KEY_TV2: "KEY_TV2", 1459 | KEY_VCR: "KEY_VCR", 1460 | KEY_VCR2: "KEY_VCR2", 1461 | KEY_SAT: "KEY_SAT", 1462 | KEY_SAT2: "KEY_SAT2", 1463 | KEY_CD: "KEY_CD", 1464 | KEY_TAPE: "KEY_TAPE", 1465 | KEY_RADIO: "KEY_RADIO", 1466 | KEY_TUNER: "KEY_TUNER", 1467 | KEY_PLAYER: "KEY_PLAYER", 1468 | KEY_TEXT: "KEY_TEXT", 1469 | KEY_DVD: "KEY_DVD", 1470 | KEY_AUX: "KEY_AUX", 1471 | KEY_MP3: "KEY_MP3", 1472 | KEY_AUDIO: "KEY_AUDIO", 1473 | KEY_VIDEO: "KEY_VIDEO", 1474 | KEY_DIRECTORY: "KEY_DIRECTORY", 1475 | KEY_LIST: "KEY_LIST", 1476 | KEY_MEMO: "KEY_MEMO", 1477 | KEY_CALENDAR: "KEY_CALENDAR", 1478 | KEY_RED: "KEY_RED", 1479 | KEY_GREEN: "KEY_GREEN", 1480 | KEY_YELLOW: "KEY_YELLOW", 1481 | KEY_BLUE: "KEY_BLUE", 1482 | KEY_CHANNELUP: "KEY_CHANNELUP", 1483 | KEY_CHANNELDOWN: "KEY_CHANNELDOWN", 1484 | KEY_FIRST: "KEY_FIRST", 1485 | KEY_LAST: "KEY_LAST", 1486 | KEY_AB: "KEY_AB", 1487 | KEY_NEXT: "KEY_NEXT", 1488 | KEY_RESTART: "KEY_RESTART", 1489 | KEY_SLOW: "KEY_SLOW", 1490 | KEY_SHUFFLE: "KEY_SHUFFLE", 1491 | KEY_BREAK: "KEY_BREAK", 1492 | KEY_PREVIOUS: "KEY_PREVIOUS", 1493 | KEY_DIGITS: "KEY_DIGITS", 1494 | KEY_TEEN: "KEY_TEEN", 1495 | KEY_TWEN: "KEY_TWEN", 1496 | KEY_VIDEOPHONE: "KEY_VIDEOPHONE", 1497 | KEY_GAMES: "KEY_GAMES", 1498 | KEY_ZOOMIN: "KEY_ZOOMIN", 1499 | KEY_ZOOMOUT: "KEY_ZOOMOUT", 1500 | KEY_ZOOMRESET: "KEY_ZOOMRESET", 1501 | KEY_WORDPROCESSOR: "KEY_WORDPROCESSOR", 1502 | KEY_EDITOR: "KEY_EDITOR", 1503 | KEY_SPREADSHEET: "KEY_SPREADSHEET", 1504 | KEY_GRAPHICSEDITOR: "KEY_GRAPHICSEDITOR", 1505 | KEY_PRESENTATION: "KEY_PRESENTATION", 1506 | KEY_DATABASE: "KEY_DATABASE", 1507 | KEY_NEWS: "KEY_NEWS", 1508 | KEY_VOICEMAIL: "KEY_VOICEMAIL", 1509 | KEY_ADDRESSBOOK: "KEY_ADDRESSBOOK", 1510 | KEY_MESSENGER: "KEY_MESSENGER", 1511 | KEY_DISPLAYTOGGLE: "KEY_DISPLAYTOGGLE", 1512 | // KEY_BRIGHTNESS_TOGGLE: "KEY_BRIGHTNESS_TOGGLE", // (KEY_DISPLAYTOGGLE) 1513 | KEY_SPELLCHECK: "KEY_SPELLCHECK", 1514 | KEY_LOGOFF: "KEY_LOGOFF", 1515 | 1516 | KEY_DOLLAR: "KEY_DOLLAR", 1517 | KEY_EURO: "KEY_EURO", 1518 | 1519 | KEY_FRAMEBACK: "KEY_FRAMEBACK", 1520 | KEY_FRAMEFORWARD: "KEY_FRAMEFORWARD", 1521 | KEY_CONTEXT_MENU: "KEY_CONTEXT_MENU", 1522 | KEY_MEDIA_REPEAT: "KEY_MEDIA_REPEAT", 1523 | KEY_10CHANNELSUP: "KEY_10CHANNELSUP", 1524 | KEY_10CHANNELSDOWN: "KEY_10CHANNELSDOWN", 1525 | KEY_IMAGES: "KEY_IMAGES", 1526 | KEY_NOTIFICATION_CENTER: "KEY_NOTIFICATION_CENTER", 1527 | KEY_PICKUP_PHONE: "KEY_PICKUP_PHONE", 1528 | KEY_HANGUP_PHONE: "KEY_HANGUP_PHONE", 1529 | 1530 | KEY_DEL_EOL: "KEY_DEL_EOL", 1531 | KEY_DEL_EOS: "KEY_DEL_EOS", 1532 | KEY_INS_LINE: "KEY_INS_LINE", 1533 | KEY_DEL_LINE: "KEY_DEL_LINE", 1534 | 1535 | KEY_FN: "KEY_FN", 1536 | KEY_FN_ESC: "KEY_FN_ESC", 1537 | KEY_FN_F1: "KEY_FN_F1", 1538 | KEY_FN_F2: "KEY_FN_F2", 1539 | KEY_FN_F3: "KEY_FN_F3", 1540 | KEY_FN_F4: "KEY_FN_F4", 1541 | KEY_FN_F5: "KEY_FN_F5", 1542 | KEY_FN_F6: "KEY_FN_F6", 1543 | KEY_FN_F7: "KEY_FN_F7", 1544 | KEY_FN_F8: "KEY_FN_F8", 1545 | KEY_FN_F9: "KEY_FN_F9", 1546 | KEY_FN_F10: "KEY_FN_F10", 1547 | KEY_FN_F11: "KEY_FN_F11", 1548 | KEY_FN_F12: "KEY_FN_F12", 1549 | KEY_FN_1: "KEY_FN_1", 1550 | KEY_FN_2: "KEY_FN_2", 1551 | KEY_FN_D: "KEY_FN_D", 1552 | KEY_FN_E: "KEY_FN_E", 1553 | KEY_FN_F: "KEY_FN_F", 1554 | KEY_FN_S: "KEY_FN_S", 1555 | KEY_FN_B: "KEY_FN_B", 1556 | KEY_FN_RIGHT_SHIFT: "KEY_FN_RIGHT_SHIFT", 1557 | 1558 | KEY_BRL_DOT1: "KEY_BRL_DOT1", 1559 | KEY_BRL_DOT2: "KEY_BRL_DOT2", 1560 | KEY_BRL_DOT3: "KEY_BRL_DOT3", 1561 | KEY_BRL_DOT4: "KEY_BRL_DOT4", 1562 | KEY_BRL_DOT5: "KEY_BRL_DOT5", 1563 | KEY_BRL_DOT6: "KEY_BRL_DOT6", 1564 | KEY_BRL_DOT7: "KEY_BRL_DOT7", 1565 | KEY_BRL_DOT8: "KEY_BRL_DOT8", 1566 | KEY_BRL_DOT9: "KEY_BRL_DOT9", 1567 | KEY_BRL_DOT10: "KEY_BRL_DOT10", 1568 | 1569 | KEY_NUMERIC_0: "KEY_NUMERIC_0", 1570 | KEY_NUMERIC_1: "KEY_NUMERIC_1", 1571 | KEY_NUMERIC_2: "KEY_NUMERIC_2", 1572 | KEY_NUMERIC_3: "KEY_NUMERIC_3", 1573 | KEY_NUMERIC_4: "KEY_NUMERIC_4", 1574 | KEY_NUMERIC_5: "KEY_NUMERIC_5", 1575 | KEY_NUMERIC_6: "KEY_NUMERIC_6", 1576 | KEY_NUMERIC_7: "KEY_NUMERIC_7", 1577 | KEY_NUMERIC_8: "KEY_NUMERIC_8", 1578 | KEY_NUMERIC_9: "KEY_NUMERIC_9", 1579 | KEY_NUMERIC_STAR: "KEY_NUMERIC_STAR", 1580 | KEY_NUMERIC_POUND: "KEY_NUMERIC_POUND", 1581 | KEY_NUMERIC_A: "KEY_NUMERIC_A", 1582 | KEY_NUMERIC_B: "KEY_NUMERIC_B", 1583 | KEY_NUMERIC_C: "KEY_NUMERIC_C", 1584 | KEY_NUMERIC_D: "KEY_NUMERIC_D", 1585 | 1586 | KEY_CAMERA_FOCUS: "KEY_CAMERA_FOCUS", 1587 | KEY_WPS_BUTTON: "KEY_WPS_BUTTON", 1588 | 1589 | KEY_TOUCHPAD_TOGGLE: "KEY_TOUCHPAD_TOGGLE", 1590 | KEY_TOUCHPAD_ON: "KEY_TOUCHPAD_ON", 1591 | KEY_TOUCHPAD_OFF: "KEY_TOUCHPAD_OFF", 1592 | 1593 | KEY_CAMERA_ZOOMIN: "KEY_CAMERA_ZOOMIN", 1594 | KEY_CAMERA_ZOOMOUT: "KEY_CAMERA_ZOOMOUT", 1595 | KEY_CAMERA_UP: "KEY_CAMERA_UP", 1596 | KEY_CAMERA_DOWN: "KEY_CAMERA_DOWN", 1597 | KEY_CAMERA_LEFT: "KEY_CAMERA_LEFT", 1598 | KEY_CAMERA_RIGHT: "KEY_CAMERA_RIGHT", 1599 | 1600 | KEY_ATTENDANT_ON: "KEY_ATTENDANT_ON", 1601 | KEY_ATTENDANT_OFF: "KEY_ATTENDANT_OFF", 1602 | KEY_ATTENDANT_TOGGLE: "KEY_ATTENDANT_TOGGLE", 1603 | KEY_LIGHTS_TOGGLE: "KEY_LIGHTS_TOGGLE", 1604 | 1605 | BTN_DPAD_UP: "BTN_DPAD_UP", 1606 | BTN_DPAD_DOWN: "BTN_DPAD_DOWN", 1607 | BTN_DPAD_LEFT: "BTN_DPAD_LEFT", 1608 | BTN_DPAD_RIGHT: "BTN_DPAD_RIGHT", 1609 | 1610 | KEY_ALS_TOGGLE: "KEY_ALS_TOGGLE", 1611 | KEY_ROTATE_LOCK_TOGGLE: "KEY_ROTATE_LOCK_TOGGLE", 1612 | 1613 | KEY_BUTTONCONFIG: "KEY_BUTTONCONFIG", 1614 | KEY_TASKMANAGER: "KEY_TASKMANAGER", 1615 | KEY_JOURNAL: "KEY_JOURNAL", 1616 | KEY_CONTROLPANEL: "KEY_CONTROLPANEL", 1617 | KEY_APPSELECT: "KEY_APPSELECT", 1618 | KEY_SCREENSAVER: "KEY_SCREENSAVER", 1619 | KEY_VOICECOMMAND: "KEY_VOICECOMMAND", 1620 | KEY_ASSISTANT: "KEY_ASSISTANT", 1621 | KEY_KBD_LAYOUT_NEXT: "KEY_KBD_LAYOUT_NEXT", 1622 | KEY_EMOJI_PICKER: "KEY_EMOJI_PICKER", 1623 | KEY_DICTATE: "KEY_DICTATE", 1624 | KEY_CAMERA_ACCESS_ENABLE: "KEY_CAMERA_ACCESS_ENABLE", 1625 | KEY_CAMERA_ACCESS_DISABLE: "KEY_CAMERA_ACCESS_DISABLE", 1626 | KEY_CAMERA_ACCESS_TOGGLE: "KEY_CAMERA_ACCESS_TOGGLE", 1627 | 1628 | KEY_BRIGHTNESS_MIN: "KEY_BRIGHTNESS_MIN", 1629 | KEY_BRIGHTNESS_MAX: "KEY_BRIGHTNESS_MAX", 1630 | 1631 | KEY_KBDINPUTASSIST_PREV: "KEY_KBDINPUTASSIST_PREV", 1632 | KEY_KBDINPUTASSIST_NEXT: "KEY_KBDINPUTASSIST_NEXT", 1633 | KEY_KBDINPUTASSIST_PREVGROUP: "KEY_KBDINPUTASSIST_PREVGROUP", 1634 | KEY_KBDINPUTASSIST_NEXTGROUP: "KEY_KBDINPUTASSIST_NEXTGROUP", 1635 | KEY_KBDINPUTASSIST_ACCEPT: "KEY_KBDINPUTASSIST_ACCEPT", 1636 | KEY_KBDINPUTASSIST_CANCEL: "KEY_KBDINPUTASSIST_CANCEL", 1637 | 1638 | KEY_RIGHT_UP: "KEY_RIGHT_UP", 1639 | KEY_RIGHT_DOWN: "KEY_RIGHT_DOWN", 1640 | KEY_LEFT_UP: "KEY_LEFT_UP", 1641 | KEY_LEFT_DOWN: "KEY_LEFT_DOWN", 1642 | 1643 | KEY_ROOT_MENU: "KEY_ROOT_MENU", 1644 | 1645 | KEY_MEDIA_TOP_MENU: "KEY_MEDIA_TOP_MENU", 1646 | KEY_NUMERIC_11: "KEY_NUMERIC_11", 1647 | KEY_NUMERIC_12: "KEY_NUMERIC_12", 1648 | 1649 | KEY_AUDIO_DESC: "KEY_AUDIO_DESC", 1650 | KEY_3D_MODE: "KEY_3D_MODE", 1651 | KEY_NEXT_FAVORITE: "KEY_NEXT_FAVORITE", 1652 | KEY_STOP_RECORD: "KEY_STOP_RECORD", 1653 | KEY_PAUSE_RECORD: "KEY_PAUSE_RECORD", 1654 | KEY_VOD: "KEY_VOD", 1655 | KEY_UNMUTE: "KEY_UNMUTE", 1656 | KEY_FASTREVERSE: "KEY_FASTREVERSE", 1657 | KEY_SLOWREVERSE: "KEY_SLOWREVERSE", 1658 | 1659 | KEY_DATA: "KEY_DATA", 1660 | KEY_ONSCREEN_KEYBOARD: "KEY_ONSCREEN_KEYBOARD", 1661 | 1662 | KEY_PRIVACY_SCREEN_TOGGLE: "KEY_PRIVACY_SCREEN_TOGGLE", 1663 | 1664 | KEY_SELECTIVE_SCREENSHOT: "KEY_SELECTIVE_SCREENSHOT", 1665 | 1666 | KEY_NEXT_ELEMENT: "KEY_NEXT_ELEMENT", 1667 | KEY_PREVIOUS_ELEMENT: "KEY_PREVIOUS_ELEMENT", 1668 | 1669 | KEY_AUTOPILOT_ENGAGE_TOGGLE: "KEY_AUTOPILOT_ENGAGE_TOGGLE", 1670 | 1671 | KEY_MARK_WAYPOINT: "KEY_MARK_WAYPOINT", 1672 | KEY_SOS: "KEY_SOS", 1673 | KEY_NAV_CHART: "KEY_NAV_CHART", 1674 | KEY_FISHING_CHART: "KEY_FISHING_CHART", 1675 | KEY_SINGLE_RANGE_RADAR: "KEY_SINGLE_RANGE_RADAR", 1676 | KEY_DUAL_RANGE_RADAR: "KEY_DUAL_RANGE_RADAR", 1677 | KEY_RADAR_OVERLAY: "KEY_RADAR_OVERLAY", 1678 | KEY_TRADITIONAL_SONAR: "KEY_TRADITIONAL_SONAR", 1679 | KEY_CLEARVU_SONAR: "KEY_CLEARVU_SONAR", 1680 | KEY_SIDEVU_SONAR: "KEY_SIDEVU_SONAR", 1681 | KEY_NAV_INFO: "KEY_NAV_INFO", 1682 | KEY_BRIGHTNESS_MENU: "KEY_BRIGHTNESS_MENU", 1683 | 1684 | KEY_MACRO1: "KEY_MACRO1", 1685 | KEY_MACRO2: "KEY_MACRO2", 1686 | KEY_MACRO3: "KEY_MACRO3", 1687 | KEY_MACRO4: "KEY_MACRO4", 1688 | KEY_MACRO5: "KEY_MACRO5", 1689 | KEY_MACRO6: "KEY_MACRO6", 1690 | KEY_MACRO7: "KEY_MACRO7", 1691 | KEY_MACRO8: "KEY_MACRO8", 1692 | KEY_MACRO9: "KEY_MACRO9", 1693 | KEY_MACRO10: "KEY_MACRO10", 1694 | KEY_MACRO11: "KEY_MACRO11", 1695 | KEY_MACRO12: "KEY_MACRO12", 1696 | KEY_MACRO13: "KEY_MACRO13", 1697 | KEY_MACRO14: "KEY_MACRO14", 1698 | KEY_MACRO15: "KEY_MACRO15", 1699 | KEY_MACRO16: "KEY_MACRO16", 1700 | KEY_MACRO17: "KEY_MACRO17", 1701 | KEY_MACRO18: "KEY_MACRO18", 1702 | KEY_MACRO19: "KEY_MACRO19", 1703 | KEY_MACRO20: "KEY_MACRO20", 1704 | KEY_MACRO21: "KEY_MACRO21", 1705 | KEY_MACRO22: "KEY_MACRO22", 1706 | KEY_MACRO23: "KEY_MACRO23", 1707 | KEY_MACRO24: "KEY_MACRO24", 1708 | KEY_MACRO25: "KEY_MACRO25", 1709 | KEY_MACRO26: "KEY_MACRO26", 1710 | KEY_MACRO27: "KEY_MACRO27", 1711 | KEY_MACRO28: "KEY_MACRO28", 1712 | KEY_MACRO29: "KEY_MACRO29", 1713 | KEY_MACRO30: "KEY_MACRO30", 1714 | 1715 | KEY_MACRO_RECORD_START: "KEY_MACRO_RECORD_START", 1716 | KEY_MACRO_RECORD_STOP: "KEY_MACRO_RECORD_STOP", 1717 | KEY_MACRO_PRESET_CYCLE: "KEY_MACRO_PRESET_CYCLE", 1718 | KEY_MACRO_PRESET1: "KEY_MACRO_PRESET1", 1719 | KEY_MACRO_PRESET2: "KEY_MACRO_PRESET2", 1720 | KEY_MACRO_PRESET3: "KEY_MACRO_PRESET3", 1721 | 1722 | KEY_KBD_LCD_MENU1: "KEY_KBD_LCD_MENU1", 1723 | KEY_KBD_LCD_MENU2: "KEY_KBD_LCD_MENU2", 1724 | KEY_KBD_LCD_MENU3: "KEY_KBD_LCD_MENU3", 1725 | KEY_KBD_LCD_MENU4: "KEY_KBD_LCD_MENU4", 1726 | KEY_KBD_LCD_MENU5: "KEY_KBD_LCD_MENU5", 1727 | 1728 | BTN_TRIGGER_HAPPY: "BTN_TRIGGER_HAPPY", 1729 | // BTN_TRIGGER_HAPPY1: "BTN_TRIGGER_HAPPY1", // (BTN_TRIGGER_HAPPY) 1730 | BTN_TRIGGER_HAPPY2: "BTN_TRIGGER_HAPPY2", 1731 | BTN_TRIGGER_HAPPY3: "BTN_TRIGGER_HAPPY3", 1732 | BTN_TRIGGER_HAPPY4: "BTN_TRIGGER_HAPPY4", 1733 | BTN_TRIGGER_HAPPY5: "BTN_TRIGGER_HAPPY5", 1734 | BTN_TRIGGER_HAPPY6: "BTN_TRIGGER_HAPPY6", 1735 | BTN_TRIGGER_HAPPY7: "BTN_TRIGGER_HAPPY7", 1736 | BTN_TRIGGER_HAPPY8: "BTN_TRIGGER_HAPPY8", 1737 | BTN_TRIGGER_HAPPY9: "BTN_TRIGGER_HAPPY9", 1738 | BTN_TRIGGER_HAPPY10: "BTN_TRIGGER_HAPPY10", 1739 | BTN_TRIGGER_HAPPY11: "BTN_TRIGGER_HAPPY11", 1740 | BTN_TRIGGER_HAPPY12: "BTN_TRIGGER_HAPPY12", 1741 | BTN_TRIGGER_HAPPY13: "BTN_TRIGGER_HAPPY13", 1742 | BTN_TRIGGER_HAPPY14: "BTN_TRIGGER_HAPPY14", 1743 | BTN_TRIGGER_HAPPY15: "BTN_TRIGGER_HAPPY15", 1744 | BTN_TRIGGER_HAPPY16: "BTN_TRIGGER_HAPPY16", 1745 | BTN_TRIGGER_HAPPY17: "BTN_TRIGGER_HAPPY17", 1746 | BTN_TRIGGER_HAPPY18: "BTN_TRIGGER_HAPPY18", 1747 | BTN_TRIGGER_HAPPY19: "BTN_TRIGGER_HAPPY19", 1748 | BTN_TRIGGER_HAPPY20: "BTN_TRIGGER_HAPPY20", 1749 | BTN_TRIGGER_HAPPY21: "BTN_TRIGGER_HAPPY21", 1750 | BTN_TRIGGER_HAPPY22: "BTN_TRIGGER_HAPPY22", 1751 | BTN_TRIGGER_HAPPY23: "BTN_TRIGGER_HAPPY23", 1752 | BTN_TRIGGER_HAPPY24: "BTN_TRIGGER_HAPPY24", 1753 | BTN_TRIGGER_HAPPY25: "BTN_TRIGGER_HAPPY25", 1754 | BTN_TRIGGER_HAPPY26: "BTN_TRIGGER_HAPPY26", 1755 | BTN_TRIGGER_HAPPY27: "BTN_TRIGGER_HAPPY27", 1756 | BTN_TRIGGER_HAPPY28: "BTN_TRIGGER_HAPPY28", 1757 | BTN_TRIGGER_HAPPY29: "BTN_TRIGGER_HAPPY29", 1758 | BTN_TRIGGER_HAPPY30: "BTN_TRIGGER_HAPPY30", 1759 | BTN_TRIGGER_HAPPY31: "BTN_TRIGGER_HAPPY31", 1760 | BTN_TRIGGER_HAPPY32: "BTN_TRIGGER_HAPPY32", 1761 | BTN_TRIGGER_HAPPY33: "BTN_TRIGGER_HAPPY33", 1762 | BTN_TRIGGER_HAPPY34: "BTN_TRIGGER_HAPPY34", 1763 | BTN_TRIGGER_HAPPY35: "BTN_TRIGGER_HAPPY35", 1764 | BTN_TRIGGER_HAPPY36: "BTN_TRIGGER_HAPPY36", 1765 | BTN_TRIGGER_HAPPY37: "BTN_TRIGGER_HAPPY37", 1766 | BTN_TRIGGER_HAPPY38: "BTN_TRIGGER_HAPPY38", 1767 | BTN_TRIGGER_HAPPY39: "BTN_TRIGGER_HAPPY39", 1768 | BTN_TRIGGER_HAPPY40: "BTN_TRIGGER_HAPPY40", 1769 | 1770 | // KEY_MIN_INTERESTING: "KEY_MIN_INTERESTING", // (KEY_MUTE) 1771 | KEY_MAX: "KEY_MAX", 1772 | KEY_CNT: "KEY_CNT", 1773 | } 1774 | 1775 | var RELToString = map[EvCode]string{ 1776 | REL_X: "REL_X", 1777 | REL_Y: "REL_Y", 1778 | REL_Z: "REL_Z", 1779 | REL_RX: "REL_RX", 1780 | REL_RY: "REL_RY", 1781 | REL_RZ: "REL_RZ", 1782 | REL_HWHEEL: "REL_HWHEEL", 1783 | REL_DIAL: "REL_DIAL", 1784 | REL_WHEEL: "REL_WHEEL", 1785 | REL_MISC: "REL_MISC", 1786 | 1787 | REL_RESERVED: "REL_RESERVED", 1788 | REL_WHEEL_HI_RES: "REL_WHEEL_HI_RES", 1789 | REL_HWHEEL_HI_RES: "REL_HWHEEL_HI_RES", 1790 | REL_MAX: "REL_MAX", 1791 | REL_CNT: "REL_CNT", 1792 | } 1793 | 1794 | var ABSToString = map[EvCode]string{ 1795 | ABS_X: "ABS_X", 1796 | ABS_Y: "ABS_Y", 1797 | ABS_Z: "ABS_Z", 1798 | ABS_RX: "ABS_RX", 1799 | ABS_RY: "ABS_RY", 1800 | ABS_RZ: "ABS_RZ", 1801 | ABS_THROTTLE: "ABS_THROTTLE", 1802 | ABS_RUDDER: "ABS_RUDDER", 1803 | ABS_WHEEL: "ABS_WHEEL", 1804 | ABS_GAS: "ABS_GAS", 1805 | ABS_BRAKE: "ABS_BRAKE", 1806 | ABS_HAT0X: "ABS_HAT0X", 1807 | ABS_HAT0Y: "ABS_HAT0Y", 1808 | ABS_HAT1X: "ABS_HAT1X", 1809 | ABS_HAT1Y: "ABS_HAT1Y", 1810 | ABS_HAT2X: "ABS_HAT2X", 1811 | ABS_HAT2Y: "ABS_HAT2Y", 1812 | ABS_HAT3X: "ABS_HAT3X", 1813 | ABS_HAT3Y: "ABS_HAT3Y", 1814 | ABS_PRESSURE: "ABS_PRESSURE", 1815 | ABS_DISTANCE: "ABS_DISTANCE", 1816 | ABS_TILT_X: "ABS_TILT_X", 1817 | ABS_TILT_Y: "ABS_TILT_Y", 1818 | ABS_TOOL_WIDTH: "ABS_TOOL_WIDTH", 1819 | 1820 | ABS_VOLUME: "ABS_VOLUME", 1821 | ABS_PROFILE: "ABS_PROFILE", 1822 | 1823 | ABS_MISC: "ABS_MISC", 1824 | 1825 | ABS_RESERVED: "ABS_RESERVED", 1826 | 1827 | ABS_MT_SLOT: "ABS_MT_SLOT", 1828 | ABS_MT_TOUCH_MAJOR: "ABS_MT_TOUCH_MAJOR", 1829 | ABS_MT_TOUCH_MINOR: "ABS_MT_TOUCH_MINOR", 1830 | ABS_MT_WIDTH_MAJOR: "ABS_MT_WIDTH_MAJOR", 1831 | ABS_MT_WIDTH_MINOR: "ABS_MT_WIDTH_MINOR", 1832 | ABS_MT_ORIENTATION: "ABS_MT_ORIENTATION", 1833 | ABS_MT_POSITION_X: "ABS_MT_POSITION_X", 1834 | ABS_MT_POSITION_Y: "ABS_MT_POSITION_Y", 1835 | ABS_MT_TOOL_TYPE: "ABS_MT_TOOL_TYPE", 1836 | ABS_MT_BLOB_ID: "ABS_MT_BLOB_ID", 1837 | ABS_MT_TRACKING_ID: "ABS_MT_TRACKING_ID", 1838 | ABS_MT_PRESSURE: "ABS_MT_PRESSURE", 1839 | ABS_MT_DISTANCE: "ABS_MT_DISTANCE", 1840 | ABS_MT_TOOL_X: "ABS_MT_TOOL_X", 1841 | ABS_MT_TOOL_Y: "ABS_MT_TOOL_Y", 1842 | 1843 | ABS_MAX: "ABS_MAX", 1844 | ABS_CNT: "ABS_CNT", 1845 | } 1846 | 1847 | var SWToString = map[EvCode]string{ 1848 | SW_LID: "SW_LID", 1849 | SW_TABLET_MODE: "SW_TABLET_MODE", 1850 | SW_HEADPHONE_INSERT: "SW_HEADPHONE_INSERT", 1851 | SW_RFKILL_ALL: "SW_RFKILL_ALL", 1852 | // SW_RADIO: "SW_RADIO", // (SW_RFKILL_ALL) 1853 | SW_MICROPHONE_INSERT: "SW_MICROPHONE_INSERT", 1854 | SW_DOCK: "SW_DOCK", 1855 | SW_LINEOUT_INSERT: "SW_LINEOUT_INSERT", 1856 | SW_JACK_PHYSICAL_INSERT: "SW_JACK_PHYSICAL_INSERT", 1857 | SW_VIDEOOUT_INSERT: "SW_VIDEOOUT_INSERT", 1858 | SW_CAMERA_LENS_COVER: "SW_CAMERA_LENS_COVER", 1859 | SW_KEYPAD_SLIDE: "SW_KEYPAD_SLIDE", 1860 | SW_FRONT_PROXIMITY: "SW_FRONT_PROXIMITY", 1861 | SW_ROTATE_LOCK: "SW_ROTATE_LOCK", 1862 | SW_LINEIN_INSERT: "SW_LINEIN_INSERT", 1863 | SW_MUTE_DEVICE: "SW_MUTE_DEVICE", 1864 | SW_PEN_INSERTED: "SW_PEN_INSERTED", 1865 | SW_MACHINE_COVER: "SW_MACHINE_COVER", 1866 | // SW_MAX: "SW_MAX", // (SW_MACHINE_COVER) 1867 | SW_CNT: "SW_CNT", 1868 | } 1869 | 1870 | var MSCToString = map[EvCode]string{ 1871 | MSC_SERIAL: "MSC_SERIAL", 1872 | MSC_PULSELED: "MSC_PULSELED", 1873 | MSC_GESTURE: "MSC_GESTURE", 1874 | MSC_RAW: "MSC_RAW", 1875 | MSC_SCAN: "MSC_SCAN", 1876 | MSC_TIMESTAMP: "MSC_TIMESTAMP", 1877 | MSC_MAX: "MSC_MAX", 1878 | MSC_CNT: "MSC_CNT", 1879 | } 1880 | 1881 | var LEDToString = map[EvCode]string{ 1882 | LED_NUML: "LED_NUML", 1883 | LED_CAPSL: "LED_CAPSL", 1884 | LED_SCROLLL: "LED_SCROLLL", 1885 | LED_COMPOSE: "LED_COMPOSE", 1886 | LED_KANA: "LED_KANA", 1887 | LED_SLEEP: "LED_SLEEP", 1888 | LED_SUSPEND: "LED_SUSPEND", 1889 | LED_MUTE: "LED_MUTE", 1890 | LED_MISC: "LED_MISC", 1891 | LED_MAIL: "LED_MAIL", 1892 | LED_CHARGING: "LED_CHARGING", 1893 | LED_MAX: "LED_MAX", 1894 | LED_CNT: "LED_CNT", 1895 | } 1896 | 1897 | var REPToString = map[EvCode]string{ 1898 | REP_DELAY: "REP_DELAY", 1899 | REP_PERIOD: "REP_PERIOD", 1900 | // REP_MAX: "REP_MAX", // (REP_PERIOD) 1901 | REP_CNT: "REP_CNT", 1902 | } 1903 | 1904 | var SNDToString = map[EvCode]string{ 1905 | SND_CLICK: "SND_CLICK", 1906 | SND_BELL: "SND_BELL", 1907 | SND_TONE: "SND_TONE", 1908 | SND_MAX: "SND_MAX", 1909 | SND_CNT: "SND_CNT", 1910 | } 1911 | 1912 | var IDToString = map[EvCode]string{ 1913 | ID_BUS: "ID_BUS", 1914 | ID_VENDOR: "ID_VENDOR", 1915 | ID_PRODUCT: "ID_PRODUCT", 1916 | ID_VERSION: "ID_VERSION", 1917 | } 1918 | 1919 | var BUSToString = map[EvCode]string{ 1920 | BUS_PCI: "BUS_PCI", 1921 | BUS_ISAPNP: "BUS_ISAPNP", 1922 | BUS_USB: "BUS_USB", 1923 | BUS_HIL: "BUS_HIL", 1924 | BUS_BLUETOOTH: "BUS_BLUETOOTH", 1925 | BUS_VIRTUAL: "BUS_VIRTUAL", 1926 | 1927 | BUS_ISA: "BUS_ISA", 1928 | BUS_I8042: "BUS_I8042", 1929 | BUS_XTKBD: "BUS_XTKBD", 1930 | BUS_RS232: "BUS_RS232", 1931 | BUS_GAMEPORT: "BUS_GAMEPORT", 1932 | BUS_PARPORT: "BUS_PARPORT", 1933 | BUS_AMIGA: "BUS_AMIGA", 1934 | BUS_ADB: "BUS_ADB", 1935 | BUS_I2C: "BUS_I2C", 1936 | BUS_HOST: "BUS_HOST", 1937 | BUS_GSC: "BUS_GSC", 1938 | BUS_ATARI: "BUS_ATARI", 1939 | BUS_SPI: "BUS_SPI", 1940 | BUS_RMI: "BUS_RMI", 1941 | BUS_CEC: "BUS_CEC", 1942 | BUS_INTEL_ISHTP: "BUS_INTEL_ISHTP", 1943 | BUS_AMD_SFH: "BUS_AMD_SFH", 1944 | } 1945 | 1946 | var MTToString = map[EvCode]string{ 1947 | MT_TOOL_FINGER: "MT_TOOL_FINGER", 1948 | MT_TOOL_PEN: "MT_TOOL_PEN", 1949 | MT_TOOL_PALM: "MT_TOOL_PALM", 1950 | MT_TOOL_DIAL: "MT_TOOL_DIAL", 1951 | MT_TOOL_MAX: "MT_TOOL_MAX", 1952 | } 1953 | 1954 | var FFToString = map[EvCode]string{ 1955 | FF_STATUS_STOPPED: "FF_STATUS_STOPPED", 1956 | FF_STATUS_PLAYING: "FF_STATUS_PLAYING", 1957 | // FF_STATUS_MAX: "FF_STATUS_MAX", // (FF_STATUS_PLAYING) 1958 | 1959 | FF_RUMBLE: "FF_RUMBLE", 1960 | FF_PERIODIC: "FF_PERIODIC", 1961 | FF_CONSTANT: "FF_CONSTANT", 1962 | FF_SPRING: "FF_SPRING", 1963 | FF_FRICTION: "FF_FRICTION", 1964 | FF_DAMPER: "FF_DAMPER", 1965 | FF_INERTIA: "FF_INERTIA", 1966 | FF_RAMP: "FF_RAMP", 1967 | 1968 | // FF_EFFECT_MIN: "FF_EFFECT_MIN", // (FF_RUMBLE) 1969 | // FF_EFFECT_MAX: "FF_EFFECT_MAX", // (FF_RAMP) 1970 | 1971 | FF_SQUARE: "FF_SQUARE", 1972 | FF_TRIANGLE: "FF_TRIANGLE", 1973 | FF_SINE: "FF_SINE", 1974 | FF_SAW_UP: "FF_SAW_UP", 1975 | FF_SAW_DOWN: "FF_SAW_DOWN", 1976 | FF_CUSTOM: "FF_CUSTOM", 1977 | 1978 | // FF_WAVEFORM_MIN: "FF_WAVEFORM_MIN", // (FF_SQUARE) 1979 | // FF_WAVEFORM_MAX: "FF_WAVEFORM_MAX", // (FF_CUSTOM) 1980 | 1981 | FF_GAIN: "FF_GAIN", 1982 | FF_AUTOCENTER: "FF_AUTOCENTER", 1983 | 1984 | // FF_MAX_EFFECTS: "FF_MAX_EFFECTS", // (FF_GAIN) 1985 | 1986 | FF_MAX: "FF_MAX", 1987 | FF_CNT: "FF_CNT", 1988 | } 1989 | 1990 | // 1991 | // Type from String 1992 | // 1993 | 1994 | var INPUTFromString = map[string]EvProp{ 1995 | "INPUT_PROP_POINTER": INPUT_PROP_POINTER, 1996 | "INPUT_PROP_DIRECT": INPUT_PROP_DIRECT, 1997 | "INPUT_PROP_BUTTONPAD": INPUT_PROP_BUTTONPAD, 1998 | "INPUT_PROP_SEMI_MT": INPUT_PROP_SEMI_MT, 1999 | "INPUT_PROP_TOPBUTTONPAD": INPUT_PROP_TOPBUTTONPAD, 2000 | "INPUT_PROP_POINTING_STICK": INPUT_PROP_POINTING_STICK, 2001 | "INPUT_PROP_ACCELEROMETER": INPUT_PROP_ACCELEROMETER, 2002 | 2003 | "INPUT_PROP_MAX": INPUT_PROP_MAX, 2004 | "INPUT_PROP_CNT": INPUT_PROP_CNT, 2005 | } 2006 | 2007 | var EVFromString = map[string]EvType{ 2008 | "EV_SYN": EV_SYN, 2009 | "EV_KEY": EV_KEY, 2010 | "EV_REL": EV_REL, 2011 | "EV_ABS": EV_ABS, 2012 | "EV_MSC": EV_MSC, 2013 | "EV_SW": EV_SW, 2014 | "EV_LED": EV_LED, 2015 | "EV_SND": EV_SND, 2016 | "EV_REP": EV_REP, 2017 | "EV_FF": EV_FF, 2018 | "EV_PWR": EV_PWR, 2019 | "EV_FF_STATUS": EV_FF_STATUS, 2020 | "EV_MAX": EV_MAX, 2021 | "EV_CNT": EV_CNT, 2022 | } 2023 | 2024 | var SYNFromString = map[string]EvCode{ 2025 | "SYN_REPORT": SYN_REPORT, 2026 | "SYN_CONFIG": SYN_CONFIG, 2027 | "SYN_MT_REPORT": SYN_MT_REPORT, 2028 | "SYN_DROPPED": SYN_DROPPED, 2029 | "SYN_MAX": SYN_MAX, 2030 | "SYN_CNT": SYN_CNT, 2031 | } 2032 | 2033 | var KEYFromString = map[string]EvCode{ 2034 | "KEY_RESERVED": KEY_RESERVED, 2035 | "KEY_ESC": KEY_ESC, 2036 | "KEY_1": KEY_1, 2037 | "KEY_2": KEY_2, 2038 | "KEY_3": KEY_3, 2039 | "KEY_4": KEY_4, 2040 | "KEY_5": KEY_5, 2041 | "KEY_6": KEY_6, 2042 | "KEY_7": KEY_7, 2043 | "KEY_8": KEY_8, 2044 | "KEY_9": KEY_9, 2045 | "KEY_0": KEY_0, 2046 | "KEY_MINUS": KEY_MINUS, 2047 | "KEY_EQUAL": KEY_EQUAL, 2048 | "KEY_BACKSPACE": KEY_BACKSPACE, 2049 | "KEY_TAB": KEY_TAB, 2050 | "KEY_Q": KEY_Q, 2051 | "KEY_W": KEY_W, 2052 | "KEY_E": KEY_E, 2053 | "KEY_R": KEY_R, 2054 | "KEY_T": KEY_T, 2055 | "KEY_Y": KEY_Y, 2056 | "KEY_U": KEY_U, 2057 | "KEY_I": KEY_I, 2058 | "KEY_O": KEY_O, 2059 | "KEY_P": KEY_P, 2060 | "KEY_LEFTBRACE": KEY_LEFTBRACE, 2061 | "KEY_RIGHTBRACE": KEY_RIGHTBRACE, 2062 | "KEY_ENTER": KEY_ENTER, 2063 | "KEY_LEFTCTRL": KEY_LEFTCTRL, 2064 | "KEY_A": KEY_A, 2065 | "KEY_S": KEY_S, 2066 | "KEY_D": KEY_D, 2067 | "KEY_F": KEY_F, 2068 | "KEY_G": KEY_G, 2069 | "KEY_H": KEY_H, 2070 | "KEY_J": KEY_J, 2071 | "KEY_K": KEY_K, 2072 | "KEY_L": KEY_L, 2073 | "KEY_SEMICOLON": KEY_SEMICOLON, 2074 | "KEY_APOSTROPHE": KEY_APOSTROPHE, 2075 | "KEY_GRAVE": KEY_GRAVE, 2076 | "KEY_LEFTSHIFT": KEY_LEFTSHIFT, 2077 | "KEY_BACKSLASH": KEY_BACKSLASH, 2078 | "KEY_Z": KEY_Z, 2079 | "KEY_X": KEY_X, 2080 | "KEY_C": KEY_C, 2081 | "KEY_V": KEY_V, 2082 | "KEY_B": KEY_B, 2083 | "KEY_N": KEY_N, 2084 | "KEY_M": KEY_M, 2085 | "KEY_COMMA": KEY_COMMA, 2086 | "KEY_DOT": KEY_DOT, 2087 | "KEY_SLASH": KEY_SLASH, 2088 | "KEY_RIGHTSHIFT": KEY_RIGHTSHIFT, 2089 | "KEY_KPASTERISK": KEY_KPASTERISK, 2090 | "KEY_LEFTALT": KEY_LEFTALT, 2091 | "KEY_SPACE": KEY_SPACE, 2092 | "KEY_CAPSLOCK": KEY_CAPSLOCK, 2093 | "KEY_F1": KEY_F1, 2094 | "KEY_F2": KEY_F2, 2095 | "KEY_F3": KEY_F3, 2096 | "KEY_F4": KEY_F4, 2097 | "KEY_F5": KEY_F5, 2098 | "KEY_F6": KEY_F6, 2099 | "KEY_F7": KEY_F7, 2100 | "KEY_F8": KEY_F8, 2101 | "KEY_F9": KEY_F9, 2102 | "KEY_F10": KEY_F10, 2103 | "KEY_NUMLOCK": KEY_NUMLOCK, 2104 | "KEY_SCROLLLOCK": KEY_SCROLLLOCK, 2105 | "KEY_KP7": KEY_KP7, 2106 | "KEY_KP8": KEY_KP8, 2107 | "KEY_KP9": KEY_KP9, 2108 | "KEY_KPMINUS": KEY_KPMINUS, 2109 | "KEY_KP4": KEY_KP4, 2110 | "KEY_KP5": KEY_KP5, 2111 | "KEY_KP6": KEY_KP6, 2112 | "KEY_KPPLUS": KEY_KPPLUS, 2113 | "KEY_KP1": KEY_KP1, 2114 | "KEY_KP2": KEY_KP2, 2115 | "KEY_KP3": KEY_KP3, 2116 | "KEY_KP0": KEY_KP0, 2117 | "KEY_KPDOT": KEY_KPDOT, 2118 | 2119 | "KEY_ZENKAKUHANKAKU": KEY_ZENKAKUHANKAKU, 2120 | "KEY_102ND": KEY_102ND, 2121 | "KEY_F11": KEY_F11, 2122 | "KEY_F12": KEY_F12, 2123 | "KEY_RO": KEY_RO, 2124 | "KEY_KATAKANA": KEY_KATAKANA, 2125 | "KEY_HIRAGANA": KEY_HIRAGANA, 2126 | "KEY_HENKAN": KEY_HENKAN, 2127 | "KEY_KATAKANAHIRAGANA": KEY_KATAKANAHIRAGANA, 2128 | "KEY_MUHENKAN": KEY_MUHENKAN, 2129 | "KEY_KPJPCOMMA": KEY_KPJPCOMMA, 2130 | "KEY_KPENTER": KEY_KPENTER, 2131 | "KEY_RIGHTCTRL": KEY_RIGHTCTRL, 2132 | "KEY_KPSLASH": KEY_KPSLASH, 2133 | "KEY_SYSRQ": KEY_SYSRQ, 2134 | "KEY_RIGHTALT": KEY_RIGHTALT, 2135 | "KEY_LINEFEED": KEY_LINEFEED, 2136 | "KEY_HOME": KEY_HOME, 2137 | "KEY_UP": KEY_UP, 2138 | "KEY_PAGEUP": KEY_PAGEUP, 2139 | "KEY_LEFT": KEY_LEFT, 2140 | "KEY_RIGHT": KEY_RIGHT, 2141 | "KEY_END": KEY_END, 2142 | "KEY_DOWN": KEY_DOWN, 2143 | "KEY_PAGEDOWN": KEY_PAGEDOWN, 2144 | "KEY_INSERT": KEY_INSERT, 2145 | "KEY_DELETE": KEY_DELETE, 2146 | "KEY_MACRO": KEY_MACRO, 2147 | "KEY_MUTE": KEY_MUTE, 2148 | "KEY_VOLUMEDOWN": KEY_VOLUMEDOWN, 2149 | "KEY_VOLUMEUP": KEY_VOLUMEUP, 2150 | "KEY_POWER": KEY_POWER, 2151 | "KEY_KPEQUAL": KEY_KPEQUAL, 2152 | "KEY_KPPLUSMINUS": KEY_KPPLUSMINUS, 2153 | "KEY_PAUSE": KEY_PAUSE, 2154 | "KEY_SCALE": KEY_SCALE, 2155 | 2156 | "KEY_KPCOMMA": KEY_KPCOMMA, 2157 | "KEY_HANGEUL": KEY_HANGEUL, 2158 | "KEY_HANGUEL": KEY_HANGUEL, 2159 | "KEY_HANJA": KEY_HANJA, 2160 | "KEY_YEN": KEY_YEN, 2161 | "KEY_LEFTMETA": KEY_LEFTMETA, 2162 | "KEY_RIGHTMETA": KEY_RIGHTMETA, 2163 | "KEY_COMPOSE": KEY_COMPOSE, 2164 | 2165 | "KEY_STOP": KEY_STOP, 2166 | "KEY_AGAIN": KEY_AGAIN, 2167 | "KEY_PROPS": KEY_PROPS, 2168 | "KEY_UNDO": KEY_UNDO, 2169 | "KEY_FRONT": KEY_FRONT, 2170 | "KEY_COPY": KEY_COPY, 2171 | "KEY_OPEN": KEY_OPEN, 2172 | "KEY_PASTE": KEY_PASTE, 2173 | "KEY_FIND": KEY_FIND, 2174 | "KEY_CUT": KEY_CUT, 2175 | "KEY_HELP": KEY_HELP, 2176 | "KEY_MENU": KEY_MENU, 2177 | "KEY_CALC": KEY_CALC, 2178 | "KEY_SETUP": KEY_SETUP, 2179 | "KEY_SLEEP": KEY_SLEEP, 2180 | "KEY_WAKEUP": KEY_WAKEUP, 2181 | "KEY_FILE": KEY_FILE, 2182 | "KEY_SENDFILE": KEY_SENDFILE, 2183 | "KEY_DELETEFILE": KEY_DELETEFILE, 2184 | "KEY_XFER": KEY_XFER, 2185 | "KEY_PROG1": KEY_PROG1, 2186 | "KEY_PROG2": KEY_PROG2, 2187 | "KEY_WWW": KEY_WWW, 2188 | "KEY_MSDOS": KEY_MSDOS, 2189 | "KEY_COFFEE": KEY_COFFEE, 2190 | "KEY_SCREENLOCK": KEY_SCREENLOCK, 2191 | "KEY_ROTATE_DISPLAY": KEY_ROTATE_DISPLAY, 2192 | "KEY_DIRECTION": KEY_DIRECTION, 2193 | "KEY_CYCLEWINDOWS": KEY_CYCLEWINDOWS, 2194 | "KEY_MAIL": KEY_MAIL, 2195 | "KEY_BOOKMARKS": KEY_BOOKMARKS, 2196 | "KEY_COMPUTER": KEY_COMPUTER, 2197 | "KEY_BACK": KEY_BACK, 2198 | "KEY_FORWARD": KEY_FORWARD, 2199 | "KEY_CLOSECD": KEY_CLOSECD, 2200 | "KEY_EJECTCD": KEY_EJECTCD, 2201 | "KEY_EJECTCLOSECD": KEY_EJECTCLOSECD, 2202 | "KEY_NEXTSONG": KEY_NEXTSONG, 2203 | "KEY_PLAYPAUSE": KEY_PLAYPAUSE, 2204 | "KEY_PREVIOUSSONG": KEY_PREVIOUSSONG, 2205 | "KEY_STOPCD": KEY_STOPCD, 2206 | "KEY_RECORD": KEY_RECORD, 2207 | "KEY_REWIND": KEY_REWIND, 2208 | "KEY_PHONE": KEY_PHONE, 2209 | "KEY_ISO": KEY_ISO, 2210 | "KEY_CONFIG": KEY_CONFIG, 2211 | "KEY_HOMEPAGE": KEY_HOMEPAGE, 2212 | "KEY_REFRESH": KEY_REFRESH, 2213 | "KEY_EXIT": KEY_EXIT, 2214 | "KEY_MOVE": KEY_MOVE, 2215 | "KEY_EDIT": KEY_EDIT, 2216 | "KEY_SCROLLUP": KEY_SCROLLUP, 2217 | "KEY_SCROLLDOWN": KEY_SCROLLDOWN, 2218 | "KEY_KPLEFTPAREN": KEY_KPLEFTPAREN, 2219 | "KEY_KPRIGHTPAREN": KEY_KPRIGHTPAREN, 2220 | "KEY_NEW": KEY_NEW, 2221 | "KEY_REDO": KEY_REDO, 2222 | 2223 | "KEY_F13": KEY_F13, 2224 | "KEY_F14": KEY_F14, 2225 | "KEY_F15": KEY_F15, 2226 | "KEY_F16": KEY_F16, 2227 | "KEY_F17": KEY_F17, 2228 | "KEY_F18": KEY_F18, 2229 | "KEY_F19": KEY_F19, 2230 | "KEY_F20": KEY_F20, 2231 | "KEY_F21": KEY_F21, 2232 | "KEY_F22": KEY_F22, 2233 | "KEY_F23": KEY_F23, 2234 | "KEY_F24": KEY_F24, 2235 | 2236 | "KEY_PLAYCD": KEY_PLAYCD, 2237 | "KEY_PAUSECD": KEY_PAUSECD, 2238 | "KEY_PROG3": KEY_PROG3, 2239 | "KEY_PROG4": KEY_PROG4, 2240 | "KEY_ALL_APPLICATIONS": KEY_ALL_APPLICATIONS, 2241 | "KEY_DASHBOARD": KEY_DASHBOARD, 2242 | "KEY_SUSPEND": KEY_SUSPEND, 2243 | "KEY_CLOSE": KEY_CLOSE, 2244 | "KEY_PLAY": KEY_PLAY, 2245 | "KEY_FASTFORWARD": KEY_FASTFORWARD, 2246 | "KEY_BASSBOOST": KEY_BASSBOOST, 2247 | "KEY_PRINT": KEY_PRINT, 2248 | "KEY_HP": KEY_HP, 2249 | "KEY_CAMERA": KEY_CAMERA, 2250 | "KEY_SOUND": KEY_SOUND, 2251 | "KEY_QUESTION": KEY_QUESTION, 2252 | "KEY_EMAIL": KEY_EMAIL, 2253 | "KEY_CHAT": KEY_CHAT, 2254 | "KEY_SEARCH": KEY_SEARCH, 2255 | "KEY_CONNECT": KEY_CONNECT, 2256 | "KEY_FINANCE": KEY_FINANCE, 2257 | "KEY_SPORT": KEY_SPORT, 2258 | "KEY_SHOP": KEY_SHOP, 2259 | "KEY_ALTERASE": KEY_ALTERASE, 2260 | "KEY_CANCEL": KEY_CANCEL, 2261 | "KEY_BRIGHTNESSDOWN": KEY_BRIGHTNESSDOWN, 2262 | "KEY_BRIGHTNESSUP": KEY_BRIGHTNESSUP, 2263 | "KEY_MEDIA": KEY_MEDIA, 2264 | 2265 | "KEY_SWITCHVIDEOMODE": KEY_SWITCHVIDEOMODE, 2266 | "KEY_KBDILLUMTOGGLE": KEY_KBDILLUMTOGGLE, 2267 | "KEY_KBDILLUMDOWN": KEY_KBDILLUMDOWN, 2268 | "KEY_KBDILLUMUP": KEY_KBDILLUMUP, 2269 | 2270 | "KEY_SEND": KEY_SEND, 2271 | "KEY_REPLY": KEY_REPLY, 2272 | "KEY_FORWARDMAIL": KEY_FORWARDMAIL, 2273 | "KEY_SAVE": KEY_SAVE, 2274 | "KEY_DOCUMENTS": KEY_DOCUMENTS, 2275 | 2276 | "KEY_BATTERY": KEY_BATTERY, 2277 | 2278 | "KEY_BLUETOOTH": KEY_BLUETOOTH, 2279 | "KEY_WLAN": KEY_WLAN, 2280 | "KEY_UWB": KEY_UWB, 2281 | 2282 | "KEY_UNKNOWN": KEY_UNKNOWN, 2283 | 2284 | "KEY_VIDEO_NEXT": KEY_VIDEO_NEXT, 2285 | "KEY_VIDEO_PREV": KEY_VIDEO_PREV, 2286 | "KEY_BRIGHTNESS_CYCLE": KEY_BRIGHTNESS_CYCLE, 2287 | "KEY_BRIGHTNESS_AUTO": KEY_BRIGHTNESS_AUTO, 2288 | "KEY_BRIGHTNESS_ZERO": KEY_BRIGHTNESS_ZERO, 2289 | "KEY_DISPLAY_OFF": KEY_DISPLAY_OFF, 2290 | 2291 | "KEY_WWAN": KEY_WWAN, 2292 | "KEY_WIMAX": KEY_WIMAX, 2293 | "KEY_RFKILL": KEY_RFKILL, 2294 | 2295 | "KEY_MICMUTE": KEY_MICMUTE, 2296 | 2297 | "BTN_MISC": BTN_MISC, 2298 | "BTN_0": BTN_0, 2299 | "BTN_1": BTN_1, 2300 | "BTN_2": BTN_2, 2301 | "BTN_3": BTN_3, 2302 | "BTN_4": BTN_4, 2303 | "BTN_5": BTN_5, 2304 | "BTN_6": BTN_6, 2305 | "BTN_7": BTN_7, 2306 | "BTN_8": BTN_8, 2307 | "BTN_9": BTN_9, 2308 | 2309 | "BTN_MOUSE": BTN_MOUSE, 2310 | "BTN_LEFT": BTN_LEFT, 2311 | "BTN_RIGHT": BTN_RIGHT, 2312 | "BTN_MIDDLE": BTN_MIDDLE, 2313 | "BTN_SIDE": BTN_SIDE, 2314 | "BTN_EXTRA": BTN_EXTRA, 2315 | "BTN_FORWARD": BTN_FORWARD, 2316 | "BTN_BACK": BTN_BACK, 2317 | "BTN_TASK": BTN_TASK, 2318 | 2319 | "BTN_JOYSTICK": BTN_JOYSTICK, 2320 | "BTN_TRIGGER": BTN_TRIGGER, 2321 | "BTN_THUMB": BTN_THUMB, 2322 | "BTN_THUMB2": BTN_THUMB2, 2323 | "BTN_TOP": BTN_TOP, 2324 | "BTN_TOP2": BTN_TOP2, 2325 | "BTN_PINKIE": BTN_PINKIE, 2326 | "BTN_BASE": BTN_BASE, 2327 | "BTN_BASE2": BTN_BASE2, 2328 | "BTN_BASE3": BTN_BASE3, 2329 | "BTN_BASE4": BTN_BASE4, 2330 | "BTN_BASE5": BTN_BASE5, 2331 | "BTN_BASE6": BTN_BASE6, 2332 | "BTN_DEAD": BTN_DEAD, 2333 | 2334 | "BTN_GAMEPAD": BTN_GAMEPAD, 2335 | "BTN_SOUTH": BTN_SOUTH, 2336 | "BTN_A": BTN_A, 2337 | "BTN_EAST": BTN_EAST, 2338 | "BTN_B": BTN_B, 2339 | "BTN_C": BTN_C, 2340 | "BTN_NORTH": BTN_NORTH, 2341 | "BTN_X": BTN_X, 2342 | "BTN_WEST": BTN_WEST, 2343 | "BTN_Y": BTN_Y, 2344 | "BTN_Z": BTN_Z, 2345 | "BTN_TL": BTN_TL, 2346 | "BTN_TR": BTN_TR, 2347 | "BTN_TL2": BTN_TL2, 2348 | "BTN_TR2": BTN_TR2, 2349 | "BTN_SELECT": BTN_SELECT, 2350 | "BTN_START": BTN_START, 2351 | "BTN_MODE": BTN_MODE, 2352 | "BTN_THUMBL": BTN_THUMBL, 2353 | "BTN_THUMBR": BTN_THUMBR, 2354 | 2355 | "BTN_DIGI": BTN_DIGI, 2356 | "BTN_TOOL_PEN": BTN_TOOL_PEN, 2357 | "BTN_TOOL_RUBBER": BTN_TOOL_RUBBER, 2358 | "BTN_TOOL_BRUSH": BTN_TOOL_BRUSH, 2359 | "BTN_TOOL_PENCIL": BTN_TOOL_PENCIL, 2360 | "BTN_TOOL_AIRBRUSH": BTN_TOOL_AIRBRUSH, 2361 | "BTN_TOOL_FINGER": BTN_TOOL_FINGER, 2362 | "BTN_TOOL_MOUSE": BTN_TOOL_MOUSE, 2363 | "BTN_TOOL_LENS": BTN_TOOL_LENS, 2364 | "BTN_TOOL_QUINTTAP": BTN_TOOL_QUINTTAP, 2365 | "BTN_STYLUS3": BTN_STYLUS3, 2366 | "BTN_TOUCH": BTN_TOUCH, 2367 | "BTN_STYLUS": BTN_STYLUS, 2368 | "BTN_STYLUS2": BTN_STYLUS2, 2369 | "BTN_TOOL_DOUBLETAP": BTN_TOOL_DOUBLETAP, 2370 | "BTN_TOOL_TRIPLETAP": BTN_TOOL_TRIPLETAP, 2371 | "BTN_TOOL_QUADTAP": BTN_TOOL_QUADTAP, 2372 | 2373 | "BTN_WHEEL": BTN_WHEEL, 2374 | "BTN_GEAR_DOWN": BTN_GEAR_DOWN, 2375 | "BTN_GEAR_UP": BTN_GEAR_UP, 2376 | 2377 | "KEY_OK": KEY_OK, 2378 | "KEY_SELECT": KEY_SELECT, 2379 | "KEY_GOTO": KEY_GOTO, 2380 | "KEY_CLEAR": KEY_CLEAR, 2381 | "KEY_POWER2": KEY_POWER2, 2382 | "KEY_OPTION": KEY_OPTION, 2383 | "KEY_INFO": KEY_INFO, 2384 | "KEY_TIME": KEY_TIME, 2385 | "KEY_VENDOR": KEY_VENDOR, 2386 | "KEY_ARCHIVE": KEY_ARCHIVE, 2387 | "KEY_PROGRAM": KEY_PROGRAM, 2388 | "KEY_CHANNEL": KEY_CHANNEL, 2389 | "KEY_FAVORITES": KEY_FAVORITES, 2390 | "KEY_EPG": KEY_EPG, 2391 | "KEY_PVR": KEY_PVR, 2392 | "KEY_MHP": KEY_MHP, 2393 | "KEY_LANGUAGE": KEY_LANGUAGE, 2394 | "KEY_TITLE": KEY_TITLE, 2395 | "KEY_SUBTITLE": KEY_SUBTITLE, 2396 | "KEY_ANGLE": KEY_ANGLE, 2397 | "KEY_FULL_SCREEN": KEY_FULL_SCREEN, 2398 | "KEY_ZOOM": KEY_ZOOM, 2399 | "KEY_MODE": KEY_MODE, 2400 | "KEY_KEYBOARD": KEY_KEYBOARD, 2401 | "KEY_ASPECT_RATIO": KEY_ASPECT_RATIO, 2402 | "KEY_SCREEN": KEY_SCREEN, 2403 | "KEY_PC": KEY_PC, 2404 | "KEY_TV": KEY_TV, 2405 | "KEY_TV2": KEY_TV2, 2406 | "KEY_VCR": KEY_VCR, 2407 | "KEY_VCR2": KEY_VCR2, 2408 | "KEY_SAT": KEY_SAT, 2409 | "KEY_SAT2": KEY_SAT2, 2410 | "KEY_CD": KEY_CD, 2411 | "KEY_TAPE": KEY_TAPE, 2412 | "KEY_RADIO": KEY_RADIO, 2413 | "KEY_TUNER": KEY_TUNER, 2414 | "KEY_PLAYER": KEY_PLAYER, 2415 | "KEY_TEXT": KEY_TEXT, 2416 | "KEY_DVD": KEY_DVD, 2417 | "KEY_AUX": KEY_AUX, 2418 | "KEY_MP3": KEY_MP3, 2419 | "KEY_AUDIO": KEY_AUDIO, 2420 | "KEY_VIDEO": KEY_VIDEO, 2421 | "KEY_DIRECTORY": KEY_DIRECTORY, 2422 | "KEY_LIST": KEY_LIST, 2423 | "KEY_MEMO": KEY_MEMO, 2424 | "KEY_CALENDAR": KEY_CALENDAR, 2425 | "KEY_RED": KEY_RED, 2426 | "KEY_GREEN": KEY_GREEN, 2427 | "KEY_YELLOW": KEY_YELLOW, 2428 | "KEY_BLUE": KEY_BLUE, 2429 | "KEY_CHANNELUP": KEY_CHANNELUP, 2430 | "KEY_CHANNELDOWN": KEY_CHANNELDOWN, 2431 | "KEY_FIRST": KEY_FIRST, 2432 | "KEY_LAST": KEY_LAST, 2433 | "KEY_AB": KEY_AB, 2434 | "KEY_NEXT": KEY_NEXT, 2435 | "KEY_RESTART": KEY_RESTART, 2436 | "KEY_SLOW": KEY_SLOW, 2437 | "KEY_SHUFFLE": KEY_SHUFFLE, 2438 | "KEY_BREAK": KEY_BREAK, 2439 | "KEY_PREVIOUS": KEY_PREVIOUS, 2440 | "KEY_DIGITS": KEY_DIGITS, 2441 | "KEY_TEEN": KEY_TEEN, 2442 | "KEY_TWEN": KEY_TWEN, 2443 | "KEY_VIDEOPHONE": KEY_VIDEOPHONE, 2444 | "KEY_GAMES": KEY_GAMES, 2445 | "KEY_ZOOMIN": KEY_ZOOMIN, 2446 | "KEY_ZOOMOUT": KEY_ZOOMOUT, 2447 | "KEY_ZOOMRESET": KEY_ZOOMRESET, 2448 | "KEY_WORDPROCESSOR": KEY_WORDPROCESSOR, 2449 | "KEY_EDITOR": KEY_EDITOR, 2450 | "KEY_SPREADSHEET": KEY_SPREADSHEET, 2451 | "KEY_GRAPHICSEDITOR": KEY_GRAPHICSEDITOR, 2452 | "KEY_PRESENTATION": KEY_PRESENTATION, 2453 | "KEY_DATABASE": KEY_DATABASE, 2454 | "KEY_NEWS": KEY_NEWS, 2455 | "KEY_VOICEMAIL": KEY_VOICEMAIL, 2456 | "KEY_ADDRESSBOOK": KEY_ADDRESSBOOK, 2457 | "KEY_MESSENGER": KEY_MESSENGER, 2458 | "KEY_DISPLAYTOGGLE": KEY_DISPLAYTOGGLE, 2459 | "KEY_BRIGHTNESS_TOGGLE": KEY_BRIGHTNESS_TOGGLE, 2460 | "KEY_SPELLCHECK": KEY_SPELLCHECK, 2461 | "KEY_LOGOFF": KEY_LOGOFF, 2462 | 2463 | "KEY_DOLLAR": KEY_DOLLAR, 2464 | "KEY_EURO": KEY_EURO, 2465 | 2466 | "KEY_FRAMEBACK": KEY_FRAMEBACK, 2467 | "KEY_FRAMEFORWARD": KEY_FRAMEFORWARD, 2468 | "KEY_CONTEXT_MENU": KEY_CONTEXT_MENU, 2469 | "KEY_MEDIA_REPEAT": KEY_MEDIA_REPEAT, 2470 | "KEY_10CHANNELSUP": KEY_10CHANNELSUP, 2471 | "KEY_10CHANNELSDOWN": KEY_10CHANNELSDOWN, 2472 | "KEY_IMAGES": KEY_IMAGES, 2473 | "KEY_NOTIFICATION_CENTER": KEY_NOTIFICATION_CENTER, 2474 | "KEY_PICKUP_PHONE": KEY_PICKUP_PHONE, 2475 | "KEY_HANGUP_PHONE": KEY_HANGUP_PHONE, 2476 | 2477 | "KEY_DEL_EOL": KEY_DEL_EOL, 2478 | "KEY_DEL_EOS": KEY_DEL_EOS, 2479 | "KEY_INS_LINE": KEY_INS_LINE, 2480 | "KEY_DEL_LINE": KEY_DEL_LINE, 2481 | 2482 | "KEY_FN": KEY_FN, 2483 | "KEY_FN_ESC": KEY_FN_ESC, 2484 | "KEY_FN_F1": KEY_FN_F1, 2485 | "KEY_FN_F2": KEY_FN_F2, 2486 | "KEY_FN_F3": KEY_FN_F3, 2487 | "KEY_FN_F4": KEY_FN_F4, 2488 | "KEY_FN_F5": KEY_FN_F5, 2489 | "KEY_FN_F6": KEY_FN_F6, 2490 | "KEY_FN_F7": KEY_FN_F7, 2491 | "KEY_FN_F8": KEY_FN_F8, 2492 | "KEY_FN_F9": KEY_FN_F9, 2493 | "KEY_FN_F10": KEY_FN_F10, 2494 | "KEY_FN_F11": KEY_FN_F11, 2495 | "KEY_FN_F12": KEY_FN_F12, 2496 | "KEY_FN_1": KEY_FN_1, 2497 | "KEY_FN_2": KEY_FN_2, 2498 | "KEY_FN_D": KEY_FN_D, 2499 | "KEY_FN_E": KEY_FN_E, 2500 | "KEY_FN_F": KEY_FN_F, 2501 | "KEY_FN_S": KEY_FN_S, 2502 | "KEY_FN_B": KEY_FN_B, 2503 | "KEY_FN_RIGHT_SHIFT": KEY_FN_RIGHT_SHIFT, 2504 | 2505 | "KEY_BRL_DOT1": KEY_BRL_DOT1, 2506 | "KEY_BRL_DOT2": KEY_BRL_DOT2, 2507 | "KEY_BRL_DOT3": KEY_BRL_DOT3, 2508 | "KEY_BRL_DOT4": KEY_BRL_DOT4, 2509 | "KEY_BRL_DOT5": KEY_BRL_DOT5, 2510 | "KEY_BRL_DOT6": KEY_BRL_DOT6, 2511 | "KEY_BRL_DOT7": KEY_BRL_DOT7, 2512 | "KEY_BRL_DOT8": KEY_BRL_DOT8, 2513 | "KEY_BRL_DOT9": KEY_BRL_DOT9, 2514 | "KEY_BRL_DOT10": KEY_BRL_DOT10, 2515 | 2516 | "KEY_NUMERIC_0": KEY_NUMERIC_0, 2517 | "KEY_NUMERIC_1": KEY_NUMERIC_1, 2518 | "KEY_NUMERIC_2": KEY_NUMERIC_2, 2519 | "KEY_NUMERIC_3": KEY_NUMERIC_3, 2520 | "KEY_NUMERIC_4": KEY_NUMERIC_4, 2521 | "KEY_NUMERIC_5": KEY_NUMERIC_5, 2522 | "KEY_NUMERIC_6": KEY_NUMERIC_6, 2523 | "KEY_NUMERIC_7": KEY_NUMERIC_7, 2524 | "KEY_NUMERIC_8": KEY_NUMERIC_8, 2525 | "KEY_NUMERIC_9": KEY_NUMERIC_9, 2526 | "KEY_NUMERIC_STAR": KEY_NUMERIC_STAR, 2527 | "KEY_NUMERIC_POUND": KEY_NUMERIC_POUND, 2528 | "KEY_NUMERIC_A": KEY_NUMERIC_A, 2529 | "KEY_NUMERIC_B": KEY_NUMERIC_B, 2530 | "KEY_NUMERIC_C": KEY_NUMERIC_C, 2531 | "KEY_NUMERIC_D": KEY_NUMERIC_D, 2532 | 2533 | "KEY_CAMERA_FOCUS": KEY_CAMERA_FOCUS, 2534 | "KEY_WPS_BUTTON": KEY_WPS_BUTTON, 2535 | 2536 | "KEY_TOUCHPAD_TOGGLE": KEY_TOUCHPAD_TOGGLE, 2537 | "KEY_TOUCHPAD_ON": KEY_TOUCHPAD_ON, 2538 | "KEY_TOUCHPAD_OFF": KEY_TOUCHPAD_OFF, 2539 | 2540 | "KEY_CAMERA_ZOOMIN": KEY_CAMERA_ZOOMIN, 2541 | "KEY_CAMERA_ZOOMOUT": KEY_CAMERA_ZOOMOUT, 2542 | "KEY_CAMERA_UP": KEY_CAMERA_UP, 2543 | "KEY_CAMERA_DOWN": KEY_CAMERA_DOWN, 2544 | "KEY_CAMERA_LEFT": KEY_CAMERA_LEFT, 2545 | "KEY_CAMERA_RIGHT": KEY_CAMERA_RIGHT, 2546 | 2547 | "KEY_ATTENDANT_ON": KEY_ATTENDANT_ON, 2548 | "KEY_ATTENDANT_OFF": KEY_ATTENDANT_OFF, 2549 | "KEY_ATTENDANT_TOGGLE": KEY_ATTENDANT_TOGGLE, 2550 | "KEY_LIGHTS_TOGGLE": KEY_LIGHTS_TOGGLE, 2551 | 2552 | "BTN_DPAD_UP": BTN_DPAD_UP, 2553 | "BTN_DPAD_DOWN": BTN_DPAD_DOWN, 2554 | "BTN_DPAD_LEFT": BTN_DPAD_LEFT, 2555 | "BTN_DPAD_RIGHT": BTN_DPAD_RIGHT, 2556 | 2557 | "KEY_ALS_TOGGLE": KEY_ALS_TOGGLE, 2558 | "KEY_ROTATE_LOCK_TOGGLE": KEY_ROTATE_LOCK_TOGGLE, 2559 | 2560 | "KEY_BUTTONCONFIG": KEY_BUTTONCONFIG, 2561 | "KEY_TASKMANAGER": KEY_TASKMANAGER, 2562 | "KEY_JOURNAL": KEY_JOURNAL, 2563 | "KEY_CONTROLPANEL": KEY_CONTROLPANEL, 2564 | "KEY_APPSELECT": KEY_APPSELECT, 2565 | "KEY_SCREENSAVER": KEY_SCREENSAVER, 2566 | "KEY_VOICECOMMAND": KEY_VOICECOMMAND, 2567 | "KEY_ASSISTANT": KEY_ASSISTANT, 2568 | "KEY_KBD_LAYOUT_NEXT": KEY_KBD_LAYOUT_NEXT, 2569 | "KEY_EMOJI_PICKER": KEY_EMOJI_PICKER, 2570 | "KEY_DICTATE": KEY_DICTATE, 2571 | "KEY_CAMERA_ACCESS_ENABLE": KEY_CAMERA_ACCESS_ENABLE, 2572 | "KEY_CAMERA_ACCESS_DISABLE": KEY_CAMERA_ACCESS_DISABLE, 2573 | "KEY_CAMERA_ACCESS_TOGGLE": KEY_CAMERA_ACCESS_TOGGLE, 2574 | 2575 | "KEY_BRIGHTNESS_MIN": KEY_BRIGHTNESS_MIN, 2576 | "KEY_BRIGHTNESS_MAX": KEY_BRIGHTNESS_MAX, 2577 | 2578 | "KEY_KBDINPUTASSIST_PREV": KEY_KBDINPUTASSIST_PREV, 2579 | "KEY_KBDINPUTASSIST_NEXT": KEY_KBDINPUTASSIST_NEXT, 2580 | "KEY_KBDINPUTASSIST_PREVGROUP": KEY_KBDINPUTASSIST_PREVGROUP, 2581 | "KEY_KBDINPUTASSIST_NEXTGROUP": KEY_KBDINPUTASSIST_NEXTGROUP, 2582 | "KEY_KBDINPUTASSIST_ACCEPT": KEY_KBDINPUTASSIST_ACCEPT, 2583 | "KEY_KBDINPUTASSIST_CANCEL": KEY_KBDINPUTASSIST_CANCEL, 2584 | 2585 | "KEY_RIGHT_UP": KEY_RIGHT_UP, 2586 | "KEY_RIGHT_DOWN": KEY_RIGHT_DOWN, 2587 | "KEY_LEFT_UP": KEY_LEFT_UP, 2588 | "KEY_LEFT_DOWN": KEY_LEFT_DOWN, 2589 | 2590 | "KEY_ROOT_MENU": KEY_ROOT_MENU, 2591 | 2592 | "KEY_MEDIA_TOP_MENU": KEY_MEDIA_TOP_MENU, 2593 | "KEY_NUMERIC_11": KEY_NUMERIC_11, 2594 | "KEY_NUMERIC_12": KEY_NUMERIC_12, 2595 | 2596 | "KEY_AUDIO_DESC": KEY_AUDIO_DESC, 2597 | "KEY_3D_MODE": KEY_3D_MODE, 2598 | "KEY_NEXT_FAVORITE": KEY_NEXT_FAVORITE, 2599 | "KEY_STOP_RECORD": KEY_STOP_RECORD, 2600 | "KEY_PAUSE_RECORD": KEY_PAUSE_RECORD, 2601 | "KEY_VOD": KEY_VOD, 2602 | "KEY_UNMUTE": KEY_UNMUTE, 2603 | "KEY_FASTREVERSE": KEY_FASTREVERSE, 2604 | "KEY_SLOWREVERSE": KEY_SLOWREVERSE, 2605 | 2606 | "KEY_DATA": KEY_DATA, 2607 | "KEY_ONSCREEN_KEYBOARD": KEY_ONSCREEN_KEYBOARD, 2608 | 2609 | "KEY_PRIVACY_SCREEN_TOGGLE": KEY_PRIVACY_SCREEN_TOGGLE, 2610 | 2611 | "KEY_SELECTIVE_SCREENSHOT": KEY_SELECTIVE_SCREENSHOT, 2612 | 2613 | "KEY_NEXT_ELEMENT": KEY_NEXT_ELEMENT, 2614 | "KEY_PREVIOUS_ELEMENT": KEY_PREVIOUS_ELEMENT, 2615 | 2616 | "KEY_AUTOPILOT_ENGAGE_TOGGLE": KEY_AUTOPILOT_ENGAGE_TOGGLE, 2617 | 2618 | "KEY_MARK_WAYPOINT": KEY_MARK_WAYPOINT, 2619 | "KEY_SOS": KEY_SOS, 2620 | "KEY_NAV_CHART": KEY_NAV_CHART, 2621 | "KEY_FISHING_CHART": KEY_FISHING_CHART, 2622 | "KEY_SINGLE_RANGE_RADAR": KEY_SINGLE_RANGE_RADAR, 2623 | "KEY_DUAL_RANGE_RADAR": KEY_DUAL_RANGE_RADAR, 2624 | "KEY_RADAR_OVERLAY": KEY_RADAR_OVERLAY, 2625 | "KEY_TRADITIONAL_SONAR": KEY_TRADITIONAL_SONAR, 2626 | "KEY_CLEARVU_SONAR": KEY_CLEARVU_SONAR, 2627 | "KEY_SIDEVU_SONAR": KEY_SIDEVU_SONAR, 2628 | "KEY_NAV_INFO": KEY_NAV_INFO, 2629 | "KEY_BRIGHTNESS_MENU": KEY_BRIGHTNESS_MENU, 2630 | 2631 | "KEY_MACRO1": KEY_MACRO1, 2632 | "KEY_MACRO2": KEY_MACRO2, 2633 | "KEY_MACRO3": KEY_MACRO3, 2634 | "KEY_MACRO4": KEY_MACRO4, 2635 | "KEY_MACRO5": KEY_MACRO5, 2636 | "KEY_MACRO6": KEY_MACRO6, 2637 | "KEY_MACRO7": KEY_MACRO7, 2638 | "KEY_MACRO8": KEY_MACRO8, 2639 | "KEY_MACRO9": KEY_MACRO9, 2640 | "KEY_MACRO10": KEY_MACRO10, 2641 | "KEY_MACRO11": KEY_MACRO11, 2642 | "KEY_MACRO12": KEY_MACRO12, 2643 | "KEY_MACRO13": KEY_MACRO13, 2644 | "KEY_MACRO14": KEY_MACRO14, 2645 | "KEY_MACRO15": KEY_MACRO15, 2646 | "KEY_MACRO16": KEY_MACRO16, 2647 | "KEY_MACRO17": KEY_MACRO17, 2648 | "KEY_MACRO18": KEY_MACRO18, 2649 | "KEY_MACRO19": KEY_MACRO19, 2650 | "KEY_MACRO20": KEY_MACRO20, 2651 | "KEY_MACRO21": KEY_MACRO21, 2652 | "KEY_MACRO22": KEY_MACRO22, 2653 | "KEY_MACRO23": KEY_MACRO23, 2654 | "KEY_MACRO24": KEY_MACRO24, 2655 | "KEY_MACRO25": KEY_MACRO25, 2656 | "KEY_MACRO26": KEY_MACRO26, 2657 | "KEY_MACRO27": KEY_MACRO27, 2658 | "KEY_MACRO28": KEY_MACRO28, 2659 | "KEY_MACRO29": KEY_MACRO29, 2660 | "KEY_MACRO30": KEY_MACRO30, 2661 | 2662 | "KEY_MACRO_RECORD_START": KEY_MACRO_RECORD_START, 2663 | "KEY_MACRO_RECORD_STOP": KEY_MACRO_RECORD_STOP, 2664 | "KEY_MACRO_PRESET_CYCLE": KEY_MACRO_PRESET_CYCLE, 2665 | "KEY_MACRO_PRESET1": KEY_MACRO_PRESET1, 2666 | "KEY_MACRO_PRESET2": KEY_MACRO_PRESET2, 2667 | "KEY_MACRO_PRESET3": KEY_MACRO_PRESET3, 2668 | 2669 | "KEY_KBD_LCD_MENU1": KEY_KBD_LCD_MENU1, 2670 | "KEY_KBD_LCD_MENU2": KEY_KBD_LCD_MENU2, 2671 | "KEY_KBD_LCD_MENU3": KEY_KBD_LCD_MENU3, 2672 | "KEY_KBD_LCD_MENU4": KEY_KBD_LCD_MENU4, 2673 | "KEY_KBD_LCD_MENU5": KEY_KBD_LCD_MENU5, 2674 | 2675 | "BTN_TRIGGER_HAPPY": BTN_TRIGGER_HAPPY, 2676 | "BTN_TRIGGER_HAPPY1": BTN_TRIGGER_HAPPY1, 2677 | "BTN_TRIGGER_HAPPY2": BTN_TRIGGER_HAPPY2, 2678 | "BTN_TRIGGER_HAPPY3": BTN_TRIGGER_HAPPY3, 2679 | "BTN_TRIGGER_HAPPY4": BTN_TRIGGER_HAPPY4, 2680 | "BTN_TRIGGER_HAPPY5": BTN_TRIGGER_HAPPY5, 2681 | "BTN_TRIGGER_HAPPY6": BTN_TRIGGER_HAPPY6, 2682 | "BTN_TRIGGER_HAPPY7": BTN_TRIGGER_HAPPY7, 2683 | "BTN_TRIGGER_HAPPY8": BTN_TRIGGER_HAPPY8, 2684 | "BTN_TRIGGER_HAPPY9": BTN_TRIGGER_HAPPY9, 2685 | "BTN_TRIGGER_HAPPY10": BTN_TRIGGER_HAPPY10, 2686 | "BTN_TRIGGER_HAPPY11": BTN_TRIGGER_HAPPY11, 2687 | "BTN_TRIGGER_HAPPY12": BTN_TRIGGER_HAPPY12, 2688 | "BTN_TRIGGER_HAPPY13": BTN_TRIGGER_HAPPY13, 2689 | "BTN_TRIGGER_HAPPY14": BTN_TRIGGER_HAPPY14, 2690 | "BTN_TRIGGER_HAPPY15": BTN_TRIGGER_HAPPY15, 2691 | "BTN_TRIGGER_HAPPY16": BTN_TRIGGER_HAPPY16, 2692 | "BTN_TRIGGER_HAPPY17": BTN_TRIGGER_HAPPY17, 2693 | "BTN_TRIGGER_HAPPY18": BTN_TRIGGER_HAPPY18, 2694 | "BTN_TRIGGER_HAPPY19": BTN_TRIGGER_HAPPY19, 2695 | "BTN_TRIGGER_HAPPY20": BTN_TRIGGER_HAPPY20, 2696 | "BTN_TRIGGER_HAPPY21": BTN_TRIGGER_HAPPY21, 2697 | "BTN_TRIGGER_HAPPY22": BTN_TRIGGER_HAPPY22, 2698 | "BTN_TRIGGER_HAPPY23": BTN_TRIGGER_HAPPY23, 2699 | "BTN_TRIGGER_HAPPY24": BTN_TRIGGER_HAPPY24, 2700 | "BTN_TRIGGER_HAPPY25": BTN_TRIGGER_HAPPY25, 2701 | "BTN_TRIGGER_HAPPY26": BTN_TRIGGER_HAPPY26, 2702 | "BTN_TRIGGER_HAPPY27": BTN_TRIGGER_HAPPY27, 2703 | "BTN_TRIGGER_HAPPY28": BTN_TRIGGER_HAPPY28, 2704 | "BTN_TRIGGER_HAPPY29": BTN_TRIGGER_HAPPY29, 2705 | "BTN_TRIGGER_HAPPY30": BTN_TRIGGER_HAPPY30, 2706 | "BTN_TRIGGER_HAPPY31": BTN_TRIGGER_HAPPY31, 2707 | "BTN_TRIGGER_HAPPY32": BTN_TRIGGER_HAPPY32, 2708 | "BTN_TRIGGER_HAPPY33": BTN_TRIGGER_HAPPY33, 2709 | "BTN_TRIGGER_HAPPY34": BTN_TRIGGER_HAPPY34, 2710 | "BTN_TRIGGER_HAPPY35": BTN_TRIGGER_HAPPY35, 2711 | "BTN_TRIGGER_HAPPY36": BTN_TRIGGER_HAPPY36, 2712 | "BTN_TRIGGER_HAPPY37": BTN_TRIGGER_HAPPY37, 2713 | "BTN_TRIGGER_HAPPY38": BTN_TRIGGER_HAPPY38, 2714 | "BTN_TRIGGER_HAPPY39": BTN_TRIGGER_HAPPY39, 2715 | "BTN_TRIGGER_HAPPY40": BTN_TRIGGER_HAPPY40, 2716 | 2717 | "KEY_MIN_INTERESTING": KEY_MIN_INTERESTING, 2718 | "KEY_MAX": KEY_MAX, 2719 | "KEY_CNT": KEY_CNT, 2720 | } 2721 | 2722 | var RELFromString = map[string]EvCode{ 2723 | "REL_X": REL_X, 2724 | "REL_Y": REL_Y, 2725 | "REL_Z": REL_Z, 2726 | "REL_RX": REL_RX, 2727 | "REL_RY": REL_RY, 2728 | "REL_RZ": REL_RZ, 2729 | "REL_HWHEEL": REL_HWHEEL, 2730 | "REL_DIAL": REL_DIAL, 2731 | "REL_WHEEL": REL_WHEEL, 2732 | "REL_MISC": REL_MISC, 2733 | 2734 | "REL_RESERVED": REL_RESERVED, 2735 | "REL_WHEEL_HI_RES": REL_WHEEL_HI_RES, 2736 | "REL_HWHEEL_HI_RES": REL_HWHEEL_HI_RES, 2737 | "REL_MAX": REL_MAX, 2738 | "REL_CNT": REL_CNT, 2739 | } 2740 | 2741 | var ABSFromString = map[string]EvCode{ 2742 | "ABS_X": ABS_X, 2743 | "ABS_Y": ABS_Y, 2744 | "ABS_Z": ABS_Z, 2745 | "ABS_RX": ABS_RX, 2746 | "ABS_RY": ABS_RY, 2747 | "ABS_RZ": ABS_RZ, 2748 | "ABS_THROTTLE": ABS_THROTTLE, 2749 | "ABS_RUDDER": ABS_RUDDER, 2750 | "ABS_WHEEL": ABS_WHEEL, 2751 | "ABS_GAS": ABS_GAS, 2752 | "ABS_BRAKE": ABS_BRAKE, 2753 | "ABS_HAT0X": ABS_HAT0X, 2754 | "ABS_HAT0Y": ABS_HAT0Y, 2755 | "ABS_HAT1X": ABS_HAT1X, 2756 | "ABS_HAT1Y": ABS_HAT1Y, 2757 | "ABS_HAT2X": ABS_HAT2X, 2758 | "ABS_HAT2Y": ABS_HAT2Y, 2759 | "ABS_HAT3X": ABS_HAT3X, 2760 | "ABS_HAT3Y": ABS_HAT3Y, 2761 | "ABS_PRESSURE": ABS_PRESSURE, 2762 | "ABS_DISTANCE": ABS_DISTANCE, 2763 | "ABS_TILT_X": ABS_TILT_X, 2764 | "ABS_TILT_Y": ABS_TILT_Y, 2765 | "ABS_TOOL_WIDTH": ABS_TOOL_WIDTH, 2766 | 2767 | "ABS_VOLUME": ABS_VOLUME, 2768 | "ABS_PROFILE": ABS_PROFILE, 2769 | 2770 | "ABS_MISC": ABS_MISC, 2771 | 2772 | "ABS_RESERVED": ABS_RESERVED, 2773 | 2774 | "ABS_MT_SLOT": ABS_MT_SLOT, 2775 | "ABS_MT_TOUCH_MAJOR": ABS_MT_TOUCH_MAJOR, 2776 | "ABS_MT_TOUCH_MINOR": ABS_MT_TOUCH_MINOR, 2777 | "ABS_MT_WIDTH_MAJOR": ABS_MT_WIDTH_MAJOR, 2778 | "ABS_MT_WIDTH_MINOR": ABS_MT_WIDTH_MINOR, 2779 | "ABS_MT_ORIENTATION": ABS_MT_ORIENTATION, 2780 | "ABS_MT_POSITION_X": ABS_MT_POSITION_X, 2781 | "ABS_MT_POSITION_Y": ABS_MT_POSITION_Y, 2782 | "ABS_MT_TOOL_TYPE": ABS_MT_TOOL_TYPE, 2783 | "ABS_MT_BLOB_ID": ABS_MT_BLOB_ID, 2784 | "ABS_MT_TRACKING_ID": ABS_MT_TRACKING_ID, 2785 | "ABS_MT_PRESSURE": ABS_MT_PRESSURE, 2786 | "ABS_MT_DISTANCE": ABS_MT_DISTANCE, 2787 | "ABS_MT_TOOL_X": ABS_MT_TOOL_X, 2788 | "ABS_MT_TOOL_Y": ABS_MT_TOOL_Y, 2789 | 2790 | "ABS_MAX": ABS_MAX, 2791 | "ABS_CNT": ABS_CNT, 2792 | } 2793 | 2794 | var SWFromString = map[string]EvCode{ 2795 | "SW_LID": SW_LID, 2796 | "SW_TABLET_MODE": SW_TABLET_MODE, 2797 | "SW_HEADPHONE_INSERT": SW_HEADPHONE_INSERT, 2798 | "SW_RFKILL_ALL": SW_RFKILL_ALL, 2799 | "SW_RADIO": SW_RADIO, 2800 | "SW_MICROPHONE_INSERT": SW_MICROPHONE_INSERT, 2801 | "SW_DOCK": SW_DOCK, 2802 | "SW_LINEOUT_INSERT": SW_LINEOUT_INSERT, 2803 | "SW_JACK_PHYSICAL_INSERT": SW_JACK_PHYSICAL_INSERT, 2804 | "SW_VIDEOOUT_INSERT": SW_VIDEOOUT_INSERT, 2805 | "SW_CAMERA_LENS_COVER": SW_CAMERA_LENS_COVER, 2806 | "SW_KEYPAD_SLIDE": SW_KEYPAD_SLIDE, 2807 | "SW_FRONT_PROXIMITY": SW_FRONT_PROXIMITY, 2808 | "SW_ROTATE_LOCK": SW_ROTATE_LOCK, 2809 | "SW_LINEIN_INSERT": SW_LINEIN_INSERT, 2810 | "SW_MUTE_DEVICE": SW_MUTE_DEVICE, 2811 | "SW_PEN_INSERTED": SW_PEN_INSERTED, 2812 | "SW_MACHINE_COVER": SW_MACHINE_COVER, 2813 | "SW_MAX": SW_MAX, 2814 | "SW_CNT": SW_CNT, 2815 | } 2816 | 2817 | var MSCFromString = map[string]EvCode{ 2818 | "MSC_SERIAL": MSC_SERIAL, 2819 | "MSC_PULSELED": MSC_PULSELED, 2820 | "MSC_GESTURE": MSC_GESTURE, 2821 | "MSC_RAW": MSC_RAW, 2822 | "MSC_SCAN": MSC_SCAN, 2823 | "MSC_TIMESTAMP": MSC_TIMESTAMP, 2824 | "MSC_MAX": MSC_MAX, 2825 | "MSC_CNT": MSC_CNT, 2826 | } 2827 | 2828 | var LEDFromString = map[string]EvCode{ 2829 | "LED_NUML": LED_NUML, 2830 | "LED_CAPSL": LED_CAPSL, 2831 | "LED_SCROLLL": LED_SCROLLL, 2832 | "LED_COMPOSE": LED_COMPOSE, 2833 | "LED_KANA": LED_KANA, 2834 | "LED_SLEEP": LED_SLEEP, 2835 | "LED_SUSPEND": LED_SUSPEND, 2836 | "LED_MUTE": LED_MUTE, 2837 | "LED_MISC": LED_MISC, 2838 | "LED_MAIL": LED_MAIL, 2839 | "LED_CHARGING": LED_CHARGING, 2840 | "LED_MAX": LED_MAX, 2841 | "LED_CNT": LED_CNT, 2842 | } 2843 | 2844 | var REPFromString = map[string]EvCode{ 2845 | "REP_DELAY": REP_DELAY, 2846 | "REP_PERIOD": REP_PERIOD, 2847 | "REP_MAX": REP_MAX, 2848 | "REP_CNT": REP_CNT, 2849 | } 2850 | 2851 | var SNDFromString = map[string]EvCode{ 2852 | "SND_CLICK": SND_CLICK, 2853 | "SND_BELL": SND_BELL, 2854 | "SND_TONE": SND_TONE, 2855 | "SND_MAX": SND_MAX, 2856 | "SND_CNT": SND_CNT, 2857 | } 2858 | 2859 | var IDFromString = map[string]EvCode{ 2860 | "ID_BUS": ID_BUS, 2861 | "ID_VENDOR": ID_VENDOR, 2862 | "ID_PRODUCT": ID_PRODUCT, 2863 | "ID_VERSION": ID_VERSION, 2864 | } 2865 | 2866 | var BUSFromString = map[string]EvCode{ 2867 | "BUS_PCI": BUS_PCI, 2868 | "BUS_ISAPNP": BUS_ISAPNP, 2869 | "BUS_USB": BUS_USB, 2870 | "BUS_HIL": BUS_HIL, 2871 | "BUS_BLUETOOTH": BUS_BLUETOOTH, 2872 | "BUS_VIRTUAL": BUS_VIRTUAL, 2873 | 2874 | "BUS_ISA": BUS_ISA, 2875 | "BUS_I8042": BUS_I8042, 2876 | "BUS_XTKBD": BUS_XTKBD, 2877 | "BUS_RS232": BUS_RS232, 2878 | "BUS_GAMEPORT": BUS_GAMEPORT, 2879 | "BUS_PARPORT": BUS_PARPORT, 2880 | "BUS_AMIGA": BUS_AMIGA, 2881 | "BUS_ADB": BUS_ADB, 2882 | "BUS_I2C": BUS_I2C, 2883 | "BUS_HOST": BUS_HOST, 2884 | "BUS_GSC": BUS_GSC, 2885 | "BUS_ATARI": BUS_ATARI, 2886 | "BUS_SPI": BUS_SPI, 2887 | "BUS_RMI": BUS_RMI, 2888 | "BUS_CEC": BUS_CEC, 2889 | "BUS_INTEL_ISHTP": BUS_INTEL_ISHTP, 2890 | "BUS_AMD_SFH": BUS_AMD_SFH, 2891 | } 2892 | 2893 | var MTFromString = map[string]EvCode{ 2894 | "MT_TOOL_FINGER": MT_TOOL_FINGER, 2895 | "MT_TOOL_PEN": MT_TOOL_PEN, 2896 | "MT_TOOL_PALM": MT_TOOL_PALM, 2897 | "MT_TOOL_DIAL": MT_TOOL_DIAL, 2898 | "MT_TOOL_MAX": MT_TOOL_MAX, 2899 | } 2900 | 2901 | var FFFromString = map[string]EvCode{ 2902 | "FF_STATUS_STOPPED": FF_STATUS_STOPPED, 2903 | "FF_STATUS_PLAYING": FF_STATUS_PLAYING, 2904 | "FF_STATUS_MAX": FF_STATUS_MAX, 2905 | 2906 | "FF_RUMBLE": FF_RUMBLE, 2907 | "FF_PERIODIC": FF_PERIODIC, 2908 | "FF_CONSTANT": FF_CONSTANT, 2909 | "FF_SPRING": FF_SPRING, 2910 | "FF_FRICTION": FF_FRICTION, 2911 | "FF_DAMPER": FF_DAMPER, 2912 | "FF_INERTIA": FF_INERTIA, 2913 | "FF_RAMP": FF_RAMP, 2914 | 2915 | "FF_EFFECT_MIN": FF_EFFECT_MIN, 2916 | "FF_EFFECT_MAX": FF_EFFECT_MAX, 2917 | 2918 | "FF_SQUARE": FF_SQUARE, 2919 | "FF_TRIANGLE": FF_TRIANGLE, 2920 | "FF_SINE": FF_SINE, 2921 | "FF_SAW_UP": FF_SAW_UP, 2922 | "FF_SAW_DOWN": FF_SAW_DOWN, 2923 | "FF_CUSTOM": FF_CUSTOM, 2924 | 2925 | "FF_WAVEFORM_MIN": FF_WAVEFORM_MIN, 2926 | "FF_WAVEFORM_MAX": FF_WAVEFORM_MAX, 2927 | 2928 | "FF_GAIN": FF_GAIN, 2929 | "FF_AUTOCENTER": FF_AUTOCENTER, 2930 | 2931 | "FF_MAX_EFFECTS": FF_MAX_EFFECTS, 2932 | 2933 | "FF_MAX": FF_MAX, 2934 | "FF_CNT": FF_CNT, 2935 | } 2936 | 2937 | // 2938 | // Type Names, useful for information/debug use only. 2939 | // When one code has two or more string representations, all available aliases are provided seperated by a slash. 2940 | // Example: KEY_COFFEE: "KEY_COFFEE/KEY_SCREENLOCK" 2941 | // 2942 | 2943 | var INPUTNames = map[EvProp]string{ 2944 | INPUT_PROP_POINTER: "INPUT_PROP_POINTER", 2945 | INPUT_PROP_DIRECT: "INPUT_PROP_DIRECT", 2946 | INPUT_PROP_BUTTONPAD: "INPUT_PROP_BUTTONPAD", 2947 | INPUT_PROP_SEMI_MT: "INPUT_PROP_SEMI_MT", 2948 | INPUT_PROP_TOPBUTTONPAD: "INPUT_PROP_TOPBUTTONPAD", 2949 | INPUT_PROP_POINTING_STICK: "INPUT_PROP_POINTING_STICK", 2950 | INPUT_PROP_ACCELEROMETER: "INPUT_PROP_ACCELEROMETER", 2951 | 2952 | INPUT_PROP_MAX: "INPUT_PROP_MAX", 2953 | INPUT_PROP_CNT: "INPUT_PROP_CNT", 2954 | } 2955 | 2956 | var EVNames = map[EvType]string{ 2957 | EV_SYN: "EV_SYN", 2958 | EV_KEY: "EV_KEY", 2959 | EV_REL: "EV_REL", 2960 | EV_ABS: "EV_ABS", 2961 | EV_MSC: "EV_MSC", 2962 | EV_SW: "EV_SW", 2963 | EV_LED: "EV_LED", 2964 | EV_SND: "EV_SND", 2965 | EV_REP: "EV_REP", 2966 | EV_FF: "EV_FF", 2967 | EV_PWR: "EV_PWR", 2968 | EV_FF_STATUS: "EV_FF_STATUS", 2969 | EV_MAX: "EV_MAX", 2970 | EV_CNT: "EV_CNT", 2971 | } 2972 | 2973 | var SYNNames = map[EvCode]string{ 2974 | SYN_REPORT: "SYN_REPORT", 2975 | SYN_CONFIG: "SYN_CONFIG", 2976 | SYN_MT_REPORT: "SYN_MT_REPORT", 2977 | SYN_DROPPED: "SYN_DROPPED", 2978 | SYN_MAX: "SYN_MAX", 2979 | SYN_CNT: "SYN_CNT", 2980 | } 2981 | 2982 | var KEYNames = map[EvCode]string{ 2983 | KEY_RESERVED: "KEY_RESERVED", 2984 | KEY_ESC: "KEY_ESC", 2985 | KEY_1: "KEY_1", 2986 | KEY_2: "KEY_2", 2987 | KEY_3: "KEY_3", 2988 | KEY_4: "KEY_4", 2989 | KEY_5: "KEY_5", 2990 | KEY_6: "KEY_6", 2991 | KEY_7: "KEY_7", 2992 | KEY_8: "KEY_8", 2993 | KEY_9: "KEY_9", 2994 | KEY_0: "KEY_0", 2995 | KEY_MINUS: "KEY_MINUS", 2996 | KEY_EQUAL: "KEY_EQUAL", 2997 | KEY_BACKSPACE: "KEY_BACKSPACE", 2998 | KEY_TAB: "KEY_TAB", 2999 | KEY_Q: "KEY_Q", 3000 | KEY_W: "KEY_W", 3001 | KEY_E: "KEY_E", 3002 | KEY_R: "KEY_R", 3003 | KEY_T: "KEY_T", 3004 | KEY_Y: "KEY_Y", 3005 | KEY_U: "KEY_U", 3006 | KEY_I: "KEY_I", 3007 | KEY_O: "KEY_O", 3008 | KEY_P: "KEY_P", 3009 | KEY_LEFTBRACE: "KEY_LEFTBRACE", 3010 | KEY_RIGHTBRACE: "KEY_RIGHTBRACE", 3011 | KEY_ENTER: "KEY_ENTER", 3012 | KEY_LEFTCTRL: "KEY_LEFTCTRL", 3013 | KEY_A: "KEY_A", 3014 | KEY_S: "KEY_S", 3015 | KEY_D: "KEY_D", 3016 | KEY_F: "KEY_F", 3017 | KEY_G: "KEY_G", 3018 | KEY_H: "KEY_H", 3019 | KEY_J: "KEY_J", 3020 | KEY_K: "KEY_K", 3021 | KEY_L: "KEY_L", 3022 | KEY_SEMICOLON: "KEY_SEMICOLON", 3023 | KEY_APOSTROPHE: "KEY_APOSTROPHE", 3024 | KEY_GRAVE: "KEY_GRAVE", 3025 | KEY_LEFTSHIFT: "KEY_LEFTSHIFT", 3026 | KEY_BACKSLASH: "KEY_BACKSLASH", 3027 | KEY_Z: "KEY_Z", 3028 | KEY_X: "KEY_X", 3029 | KEY_C: "KEY_C", 3030 | KEY_V: "KEY_V", 3031 | KEY_B: "KEY_B", 3032 | KEY_N: "KEY_N", 3033 | KEY_M: "KEY_M", 3034 | KEY_COMMA: "KEY_COMMA", 3035 | KEY_DOT: "KEY_DOT", 3036 | KEY_SLASH: "KEY_SLASH", 3037 | KEY_RIGHTSHIFT: "KEY_RIGHTSHIFT", 3038 | KEY_KPASTERISK: "KEY_KPASTERISK", 3039 | KEY_LEFTALT: "KEY_LEFTALT", 3040 | KEY_SPACE: "KEY_SPACE", 3041 | KEY_CAPSLOCK: "KEY_CAPSLOCK", 3042 | KEY_F1: "KEY_F1", 3043 | KEY_F2: "KEY_F2", 3044 | KEY_F3: "KEY_F3", 3045 | KEY_F4: "KEY_F4", 3046 | KEY_F5: "KEY_F5", 3047 | KEY_F6: "KEY_F6", 3048 | KEY_F7: "KEY_F7", 3049 | KEY_F8: "KEY_F8", 3050 | KEY_F9: "KEY_F9", 3051 | KEY_F10: "KEY_F10", 3052 | KEY_NUMLOCK: "KEY_NUMLOCK", 3053 | KEY_SCROLLLOCK: "KEY_SCROLLLOCK", 3054 | KEY_KP7: "KEY_KP7", 3055 | KEY_KP8: "KEY_KP8", 3056 | KEY_KP9: "KEY_KP9", 3057 | KEY_KPMINUS: "KEY_KPMINUS", 3058 | KEY_KP4: "KEY_KP4", 3059 | KEY_KP5: "KEY_KP5", 3060 | KEY_KP6: "KEY_KP6", 3061 | KEY_KPPLUS: "KEY_KPPLUS", 3062 | KEY_KP1: "KEY_KP1", 3063 | KEY_KP2: "KEY_KP2", 3064 | KEY_KP3: "KEY_KP3", 3065 | KEY_KP0: "KEY_KP0", 3066 | KEY_KPDOT: "KEY_KPDOT", 3067 | 3068 | KEY_ZENKAKUHANKAKU: "KEY_ZENKAKUHANKAKU", 3069 | KEY_102ND: "KEY_102ND", 3070 | KEY_F11: "KEY_F11", 3071 | KEY_F12: "KEY_F12", 3072 | KEY_RO: "KEY_RO", 3073 | KEY_KATAKANA: "KEY_KATAKANA", 3074 | KEY_HIRAGANA: "KEY_HIRAGANA", 3075 | KEY_HENKAN: "KEY_HENKAN", 3076 | KEY_KATAKANAHIRAGANA: "KEY_KATAKANAHIRAGANA", 3077 | KEY_MUHENKAN: "KEY_MUHENKAN", 3078 | KEY_KPJPCOMMA: "KEY_KPJPCOMMA", 3079 | KEY_KPENTER: "KEY_KPENTER", 3080 | KEY_RIGHTCTRL: "KEY_RIGHTCTRL", 3081 | KEY_KPSLASH: "KEY_KPSLASH", 3082 | KEY_SYSRQ: "KEY_SYSRQ", 3083 | KEY_RIGHTALT: "KEY_RIGHTALT", 3084 | KEY_LINEFEED: "KEY_LINEFEED", 3085 | KEY_HOME: "KEY_HOME", 3086 | KEY_UP: "KEY_UP", 3087 | KEY_PAGEUP: "KEY_PAGEUP", 3088 | KEY_LEFT: "KEY_LEFT", 3089 | KEY_RIGHT: "KEY_RIGHT", 3090 | KEY_END: "KEY_END", 3091 | KEY_DOWN: "KEY_DOWN", 3092 | KEY_PAGEDOWN: "KEY_PAGEDOWN", 3093 | KEY_INSERT: "KEY_INSERT", 3094 | KEY_DELETE: "KEY_DELETE", 3095 | KEY_MACRO: "KEY_MACRO", 3096 | KEY_MUTE: "KEY_MUTE/KEY_MIN_INTERESTING", 3097 | KEY_VOLUMEDOWN: "KEY_VOLUMEDOWN", 3098 | KEY_VOLUMEUP: "KEY_VOLUMEUP", 3099 | KEY_POWER: "KEY_POWER", 3100 | KEY_KPEQUAL: "KEY_KPEQUAL", 3101 | KEY_KPPLUSMINUS: "KEY_KPPLUSMINUS", 3102 | KEY_PAUSE: "KEY_PAUSE", 3103 | KEY_SCALE: "KEY_SCALE", 3104 | 3105 | KEY_KPCOMMA: "KEY_KPCOMMA", 3106 | KEY_HANGEUL: "KEY_HANGEUL/KEY_HANGUEL", 3107 | KEY_HANJA: "KEY_HANJA", 3108 | KEY_YEN: "KEY_YEN", 3109 | KEY_LEFTMETA: "KEY_LEFTMETA", 3110 | KEY_RIGHTMETA: "KEY_RIGHTMETA", 3111 | KEY_COMPOSE: "KEY_COMPOSE", 3112 | 3113 | KEY_STOP: "KEY_STOP", 3114 | KEY_AGAIN: "KEY_AGAIN", 3115 | KEY_PROPS: "KEY_PROPS", 3116 | KEY_UNDO: "KEY_UNDO", 3117 | KEY_FRONT: "KEY_FRONT", 3118 | KEY_COPY: "KEY_COPY", 3119 | KEY_OPEN: "KEY_OPEN", 3120 | KEY_PASTE: "KEY_PASTE", 3121 | KEY_FIND: "KEY_FIND", 3122 | KEY_CUT: "KEY_CUT", 3123 | KEY_HELP: "KEY_HELP", 3124 | KEY_MENU: "KEY_MENU", 3125 | KEY_CALC: "KEY_CALC", 3126 | KEY_SETUP: "KEY_SETUP", 3127 | KEY_SLEEP: "KEY_SLEEP", 3128 | KEY_WAKEUP: "KEY_WAKEUP", 3129 | KEY_FILE: "KEY_FILE", 3130 | KEY_SENDFILE: "KEY_SENDFILE", 3131 | KEY_DELETEFILE: "KEY_DELETEFILE", 3132 | KEY_XFER: "KEY_XFER", 3133 | KEY_PROG1: "KEY_PROG1", 3134 | KEY_PROG2: "KEY_PROG2", 3135 | KEY_WWW: "KEY_WWW", 3136 | KEY_MSDOS: "KEY_MSDOS", 3137 | KEY_COFFEE: "KEY_COFFEE/KEY_SCREENLOCK", 3138 | KEY_ROTATE_DISPLAY: "KEY_ROTATE_DISPLAY/KEY_DIRECTION", 3139 | KEY_CYCLEWINDOWS: "KEY_CYCLEWINDOWS", 3140 | KEY_MAIL: "KEY_MAIL", 3141 | KEY_BOOKMARKS: "KEY_BOOKMARKS", 3142 | KEY_COMPUTER: "KEY_COMPUTER", 3143 | KEY_BACK: "KEY_BACK", 3144 | KEY_FORWARD: "KEY_FORWARD", 3145 | KEY_CLOSECD: "KEY_CLOSECD", 3146 | KEY_EJECTCD: "KEY_EJECTCD", 3147 | KEY_EJECTCLOSECD: "KEY_EJECTCLOSECD", 3148 | KEY_NEXTSONG: "KEY_NEXTSONG", 3149 | KEY_PLAYPAUSE: "KEY_PLAYPAUSE", 3150 | KEY_PREVIOUSSONG: "KEY_PREVIOUSSONG", 3151 | KEY_STOPCD: "KEY_STOPCD", 3152 | KEY_RECORD: "KEY_RECORD", 3153 | KEY_REWIND: "KEY_REWIND", 3154 | KEY_PHONE: "KEY_PHONE", 3155 | KEY_ISO: "KEY_ISO", 3156 | KEY_CONFIG: "KEY_CONFIG", 3157 | KEY_HOMEPAGE: "KEY_HOMEPAGE", 3158 | KEY_REFRESH: "KEY_REFRESH", 3159 | KEY_EXIT: "KEY_EXIT", 3160 | KEY_MOVE: "KEY_MOVE", 3161 | KEY_EDIT: "KEY_EDIT", 3162 | KEY_SCROLLUP: "KEY_SCROLLUP", 3163 | KEY_SCROLLDOWN: "KEY_SCROLLDOWN", 3164 | KEY_KPLEFTPAREN: "KEY_KPLEFTPAREN", 3165 | KEY_KPRIGHTPAREN: "KEY_KPRIGHTPAREN", 3166 | KEY_NEW: "KEY_NEW", 3167 | KEY_REDO: "KEY_REDO", 3168 | 3169 | KEY_F13: "KEY_F13", 3170 | KEY_F14: "KEY_F14", 3171 | KEY_F15: "KEY_F15", 3172 | KEY_F16: "KEY_F16", 3173 | KEY_F17: "KEY_F17", 3174 | KEY_F18: "KEY_F18", 3175 | KEY_F19: "KEY_F19", 3176 | KEY_F20: "KEY_F20", 3177 | KEY_F21: "KEY_F21", 3178 | KEY_F22: "KEY_F22", 3179 | KEY_F23: "KEY_F23", 3180 | KEY_F24: "KEY_F24", 3181 | 3182 | KEY_PLAYCD: "KEY_PLAYCD", 3183 | KEY_PAUSECD: "KEY_PAUSECD", 3184 | KEY_PROG3: "KEY_PROG3", 3185 | KEY_PROG4: "KEY_PROG4", 3186 | KEY_ALL_APPLICATIONS: "KEY_ALL_APPLICATIONS/KEY_DASHBOARD", 3187 | KEY_SUSPEND: "KEY_SUSPEND", 3188 | KEY_CLOSE: "KEY_CLOSE", 3189 | KEY_PLAY: "KEY_PLAY", 3190 | KEY_FASTFORWARD: "KEY_FASTFORWARD", 3191 | KEY_BASSBOOST: "KEY_BASSBOOST", 3192 | KEY_PRINT: "KEY_PRINT", 3193 | KEY_HP: "KEY_HP", 3194 | KEY_CAMERA: "KEY_CAMERA", 3195 | KEY_SOUND: "KEY_SOUND", 3196 | KEY_QUESTION: "KEY_QUESTION", 3197 | KEY_EMAIL: "KEY_EMAIL", 3198 | KEY_CHAT: "KEY_CHAT", 3199 | KEY_SEARCH: "KEY_SEARCH", 3200 | KEY_CONNECT: "KEY_CONNECT", 3201 | KEY_FINANCE: "KEY_FINANCE", 3202 | KEY_SPORT: "KEY_SPORT", 3203 | KEY_SHOP: "KEY_SHOP", 3204 | KEY_ALTERASE: "KEY_ALTERASE", 3205 | KEY_CANCEL: "KEY_CANCEL", 3206 | KEY_BRIGHTNESSDOWN: "KEY_BRIGHTNESSDOWN", 3207 | KEY_BRIGHTNESSUP: "KEY_BRIGHTNESSUP", 3208 | KEY_MEDIA: "KEY_MEDIA", 3209 | 3210 | KEY_SWITCHVIDEOMODE: "KEY_SWITCHVIDEOMODE", 3211 | KEY_KBDILLUMTOGGLE: "KEY_KBDILLUMTOGGLE", 3212 | KEY_KBDILLUMDOWN: "KEY_KBDILLUMDOWN", 3213 | KEY_KBDILLUMUP: "KEY_KBDILLUMUP", 3214 | 3215 | KEY_SEND: "KEY_SEND", 3216 | KEY_REPLY: "KEY_REPLY", 3217 | KEY_FORWARDMAIL: "KEY_FORWARDMAIL", 3218 | KEY_SAVE: "KEY_SAVE", 3219 | KEY_DOCUMENTS: "KEY_DOCUMENTS", 3220 | 3221 | KEY_BATTERY: "KEY_BATTERY", 3222 | 3223 | KEY_BLUETOOTH: "KEY_BLUETOOTH", 3224 | KEY_WLAN: "KEY_WLAN", 3225 | KEY_UWB: "KEY_UWB", 3226 | 3227 | KEY_UNKNOWN: "KEY_UNKNOWN", 3228 | 3229 | KEY_VIDEO_NEXT: "KEY_VIDEO_NEXT", 3230 | KEY_VIDEO_PREV: "KEY_VIDEO_PREV", 3231 | KEY_BRIGHTNESS_CYCLE: "KEY_BRIGHTNESS_CYCLE", 3232 | KEY_BRIGHTNESS_AUTO: "KEY_BRIGHTNESS_AUTO/KEY_BRIGHTNESS_ZERO", 3233 | KEY_DISPLAY_OFF: "KEY_DISPLAY_OFF", 3234 | 3235 | KEY_WWAN: "KEY_WWAN/KEY_WIMAX", 3236 | KEY_RFKILL: "KEY_RFKILL", 3237 | 3238 | KEY_MICMUTE: "KEY_MICMUTE", 3239 | 3240 | BTN_MISC: "BTN_MISC/BTN_0", 3241 | BTN_1: "BTN_1", 3242 | BTN_2: "BTN_2", 3243 | BTN_3: "BTN_3", 3244 | BTN_4: "BTN_4", 3245 | BTN_5: "BTN_5", 3246 | BTN_6: "BTN_6", 3247 | BTN_7: "BTN_7", 3248 | BTN_8: "BTN_8", 3249 | BTN_9: "BTN_9", 3250 | 3251 | BTN_MOUSE: "BTN_MOUSE/BTN_LEFT", 3252 | BTN_RIGHT: "BTN_RIGHT", 3253 | BTN_MIDDLE: "BTN_MIDDLE", 3254 | BTN_SIDE: "BTN_SIDE", 3255 | BTN_EXTRA: "BTN_EXTRA", 3256 | BTN_FORWARD: "BTN_FORWARD", 3257 | BTN_BACK: "BTN_BACK", 3258 | BTN_TASK: "BTN_TASK", 3259 | 3260 | BTN_JOYSTICK: "BTN_JOYSTICK/BTN_TRIGGER", 3261 | BTN_THUMB: "BTN_THUMB", 3262 | BTN_THUMB2: "BTN_THUMB2", 3263 | BTN_TOP: "BTN_TOP", 3264 | BTN_TOP2: "BTN_TOP2", 3265 | BTN_PINKIE: "BTN_PINKIE", 3266 | BTN_BASE: "BTN_BASE", 3267 | BTN_BASE2: "BTN_BASE2", 3268 | BTN_BASE3: "BTN_BASE3", 3269 | BTN_BASE4: "BTN_BASE4", 3270 | BTN_BASE5: "BTN_BASE5", 3271 | BTN_BASE6: "BTN_BASE6", 3272 | BTN_DEAD: "BTN_DEAD", 3273 | 3274 | BTN_GAMEPAD: "BTN_GAMEPAD/BTN_SOUTH/BTN_A", 3275 | BTN_EAST: "BTN_EAST/BTN_B", 3276 | BTN_C: "BTN_C", 3277 | BTN_NORTH: "BTN_NORTH/BTN_X", 3278 | BTN_WEST: "BTN_WEST/BTN_Y", 3279 | BTN_Z: "BTN_Z", 3280 | BTN_TL: "BTN_TL", 3281 | BTN_TR: "BTN_TR", 3282 | BTN_TL2: "BTN_TL2", 3283 | BTN_TR2: "BTN_TR2", 3284 | BTN_SELECT: "BTN_SELECT", 3285 | BTN_START: "BTN_START", 3286 | BTN_MODE: "BTN_MODE", 3287 | BTN_THUMBL: "BTN_THUMBL", 3288 | BTN_THUMBR: "BTN_THUMBR", 3289 | 3290 | BTN_DIGI: "BTN_DIGI/BTN_TOOL_PEN", 3291 | BTN_TOOL_RUBBER: "BTN_TOOL_RUBBER", 3292 | BTN_TOOL_BRUSH: "BTN_TOOL_BRUSH", 3293 | BTN_TOOL_PENCIL: "BTN_TOOL_PENCIL", 3294 | BTN_TOOL_AIRBRUSH: "BTN_TOOL_AIRBRUSH", 3295 | BTN_TOOL_FINGER: "BTN_TOOL_FINGER", 3296 | BTN_TOOL_MOUSE: "BTN_TOOL_MOUSE", 3297 | BTN_TOOL_LENS: "BTN_TOOL_LENS", 3298 | BTN_TOOL_QUINTTAP: "BTN_TOOL_QUINTTAP", 3299 | BTN_STYLUS3: "BTN_STYLUS3", 3300 | BTN_TOUCH: "BTN_TOUCH", 3301 | BTN_STYLUS: "BTN_STYLUS", 3302 | BTN_STYLUS2: "BTN_STYLUS2", 3303 | BTN_TOOL_DOUBLETAP: "BTN_TOOL_DOUBLETAP", 3304 | BTN_TOOL_TRIPLETAP: "BTN_TOOL_TRIPLETAP", 3305 | BTN_TOOL_QUADTAP: "BTN_TOOL_QUADTAP", 3306 | 3307 | BTN_WHEEL: "BTN_WHEEL/BTN_GEAR_DOWN", 3308 | BTN_GEAR_UP: "BTN_GEAR_UP", 3309 | 3310 | KEY_OK: "KEY_OK", 3311 | KEY_SELECT: "KEY_SELECT", 3312 | KEY_GOTO: "KEY_GOTO", 3313 | KEY_CLEAR: "KEY_CLEAR", 3314 | KEY_POWER2: "KEY_POWER2", 3315 | KEY_OPTION: "KEY_OPTION", 3316 | KEY_INFO: "KEY_INFO", 3317 | KEY_TIME: "KEY_TIME", 3318 | KEY_VENDOR: "KEY_VENDOR", 3319 | KEY_ARCHIVE: "KEY_ARCHIVE", 3320 | KEY_PROGRAM: "KEY_PROGRAM", 3321 | KEY_CHANNEL: "KEY_CHANNEL", 3322 | KEY_FAVORITES: "KEY_FAVORITES", 3323 | KEY_EPG: "KEY_EPG", 3324 | KEY_PVR: "KEY_PVR", 3325 | KEY_MHP: "KEY_MHP", 3326 | KEY_LANGUAGE: "KEY_LANGUAGE", 3327 | KEY_TITLE: "KEY_TITLE", 3328 | KEY_SUBTITLE: "KEY_SUBTITLE", 3329 | KEY_ANGLE: "KEY_ANGLE", 3330 | KEY_FULL_SCREEN: "KEY_FULL_SCREEN/KEY_ZOOM", 3331 | KEY_MODE: "KEY_MODE", 3332 | KEY_KEYBOARD: "KEY_KEYBOARD", 3333 | KEY_ASPECT_RATIO: "KEY_ASPECT_RATIO/KEY_SCREEN", 3334 | KEY_PC: "KEY_PC", 3335 | KEY_TV: "KEY_TV", 3336 | KEY_TV2: "KEY_TV2", 3337 | KEY_VCR: "KEY_VCR", 3338 | KEY_VCR2: "KEY_VCR2", 3339 | KEY_SAT: "KEY_SAT", 3340 | KEY_SAT2: "KEY_SAT2", 3341 | KEY_CD: "KEY_CD", 3342 | KEY_TAPE: "KEY_TAPE", 3343 | KEY_RADIO: "KEY_RADIO", 3344 | KEY_TUNER: "KEY_TUNER", 3345 | KEY_PLAYER: "KEY_PLAYER", 3346 | KEY_TEXT: "KEY_TEXT", 3347 | KEY_DVD: "KEY_DVD", 3348 | KEY_AUX: "KEY_AUX", 3349 | KEY_MP3: "KEY_MP3", 3350 | KEY_AUDIO: "KEY_AUDIO", 3351 | KEY_VIDEO: "KEY_VIDEO", 3352 | KEY_DIRECTORY: "KEY_DIRECTORY", 3353 | KEY_LIST: "KEY_LIST", 3354 | KEY_MEMO: "KEY_MEMO", 3355 | KEY_CALENDAR: "KEY_CALENDAR", 3356 | KEY_RED: "KEY_RED", 3357 | KEY_GREEN: "KEY_GREEN", 3358 | KEY_YELLOW: "KEY_YELLOW", 3359 | KEY_BLUE: "KEY_BLUE", 3360 | KEY_CHANNELUP: "KEY_CHANNELUP", 3361 | KEY_CHANNELDOWN: "KEY_CHANNELDOWN", 3362 | KEY_FIRST: "KEY_FIRST", 3363 | KEY_LAST: "KEY_LAST", 3364 | KEY_AB: "KEY_AB", 3365 | KEY_NEXT: "KEY_NEXT", 3366 | KEY_RESTART: "KEY_RESTART", 3367 | KEY_SLOW: "KEY_SLOW", 3368 | KEY_SHUFFLE: "KEY_SHUFFLE", 3369 | KEY_BREAK: "KEY_BREAK", 3370 | KEY_PREVIOUS: "KEY_PREVIOUS", 3371 | KEY_DIGITS: "KEY_DIGITS", 3372 | KEY_TEEN: "KEY_TEEN", 3373 | KEY_TWEN: "KEY_TWEN", 3374 | KEY_VIDEOPHONE: "KEY_VIDEOPHONE", 3375 | KEY_GAMES: "KEY_GAMES", 3376 | KEY_ZOOMIN: "KEY_ZOOMIN", 3377 | KEY_ZOOMOUT: "KEY_ZOOMOUT", 3378 | KEY_ZOOMRESET: "KEY_ZOOMRESET", 3379 | KEY_WORDPROCESSOR: "KEY_WORDPROCESSOR", 3380 | KEY_EDITOR: "KEY_EDITOR", 3381 | KEY_SPREADSHEET: "KEY_SPREADSHEET", 3382 | KEY_GRAPHICSEDITOR: "KEY_GRAPHICSEDITOR", 3383 | KEY_PRESENTATION: "KEY_PRESENTATION", 3384 | KEY_DATABASE: "KEY_DATABASE", 3385 | KEY_NEWS: "KEY_NEWS", 3386 | KEY_VOICEMAIL: "KEY_VOICEMAIL", 3387 | KEY_ADDRESSBOOK: "KEY_ADDRESSBOOK", 3388 | KEY_MESSENGER: "KEY_MESSENGER", 3389 | KEY_DISPLAYTOGGLE: "KEY_DISPLAYTOGGLE/KEY_BRIGHTNESS_TOGGLE", 3390 | KEY_SPELLCHECK: "KEY_SPELLCHECK", 3391 | KEY_LOGOFF: "KEY_LOGOFF", 3392 | 3393 | KEY_DOLLAR: "KEY_DOLLAR", 3394 | KEY_EURO: "KEY_EURO", 3395 | 3396 | KEY_FRAMEBACK: "KEY_FRAMEBACK", 3397 | KEY_FRAMEFORWARD: "KEY_FRAMEFORWARD", 3398 | KEY_CONTEXT_MENU: "KEY_CONTEXT_MENU", 3399 | KEY_MEDIA_REPEAT: "KEY_MEDIA_REPEAT", 3400 | KEY_10CHANNELSUP: "KEY_10CHANNELSUP", 3401 | KEY_10CHANNELSDOWN: "KEY_10CHANNELSDOWN", 3402 | KEY_IMAGES: "KEY_IMAGES", 3403 | KEY_NOTIFICATION_CENTER: "KEY_NOTIFICATION_CENTER", 3404 | KEY_PICKUP_PHONE: "KEY_PICKUP_PHONE", 3405 | KEY_HANGUP_PHONE: "KEY_HANGUP_PHONE", 3406 | 3407 | KEY_DEL_EOL: "KEY_DEL_EOL", 3408 | KEY_DEL_EOS: "KEY_DEL_EOS", 3409 | KEY_INS_LINE: "KEY_INS_LINE", 3410 | KEY_DEL_LINE: "KEY_DEL_LINE", 3411 | 3412 | KEY_FN: "KEY_FN", 3413 | KEY_FN_ESC: "KEY_FN_ESC", 3414 | KEY_FN_F1: "KEY_FN_F1", 3415 | KEY_FN_F2: "KEY_FN_F2", 3416 | KEY_FN_F3: "KEY_FN_F3", 3417 | KEY_FN_F4: "KEY_FN_F4", 3418 | KEY_FN_F5: "KEY_FN_F5", 3419 | KEY_FN_F6: "KEY_FN_F6", 3420 | KEY_FN_F7: "KEY_FN_F7", 3421 | KEY_FN_F8: "KEY_FN_F8", 3422 | KEY_FN_F9: "KEY_FN_F9", 3423 | KEY_FN_F10: "KEY_FN_F10", 3424 | KEY_FN_F11: "KEY_FN_F11", 3425 | KEY_FN_F12: "KEY_FN_F12", 3426 | KEY_FN_1: "KEY_FN_1", 3427 | KEY_FN_2: "KEY_FN_2", 3428 | KEY_FN_D: "KEY_FN_D", 3429 | KEY_FN_E: "KEY_FN_E", 3430 | KEY_FN_F: "KEY_FN_F", 3431 | KEY_FN_S: "KEY_FN_S", 3432 | KEY_FN_B: "KEY_FN_B", 3433 | KEY_FN_RIGHT_SHIFT: "KEY_FN_RIGHT_SHIFT", 3434 | 3435 | KEY_BRL_DOT1: "KEY_BRL_DOT1", 3436 | KEY_BRL_DOT2: "KEY_BRL_DOT2", 3437 | KEY_BRL_DOT3: "KEY_BRL_DOT3", 3438 | KEY_BRL_DOT4: "KEY_BRL_DOT4", 3439 | KEY_BRL_DOT5: "KEY_BRL_DOT5", 3440 | KEY_BRL_DOT6: "KEY_BRL_DOT6", 3441 | KEY_BRL_DOT7: "KEY_BRL_DOT7", 3442 | KEY_BRL_DOT8: "KEY_BRL_DOT8", 3443 | KEY_BRL_DOT9: "KEY_BRL_DOT9", 3444 | KEY_BRL_DOT10: "KEY_BRL_DOT10", 3445 | 3446 | KEY_NUMERIC_0: "KEY_NUMERIC_0", 3447 | KEY_NUMERIC_1: "KEY_NUMERIC_1", 3448 | KEY_NUMERIC_2: "KEY_NUMERIC_2", 3449 | KEY_NUMERIC_3: "KEY_NUMERIC_3", 3450 | KEY_NUMERIC_4: "KEY_NUMERIC_4", 3451 | KEY_NUMERIC_5: "KEY_NUMERIC_5", 3452 | KEY_NUMERIC_6: "KEY_NUMERIC_6", 3453 | KEY_NUMERIC_7: "KEY_NUMERIC_7", 3454 | KEY_NUMERIC_8: "KEY_NUMERIC_8", 3455 | KEY_NUMERIC_9: "KEY_NUMERIC_9", 3456 | KEY_NUMERIC_STAR: "KEY_NUMERIC_STAR", 3457 | KEY_NUMERIC_POUND: "KEY_NUMERIC_POUND", 3458 | KEY_NUMERIC_A: "KEY_NUMERIC_A", 3459 | KEY_NUMERIC_B: "KEY_NUMERIC_B", 3460 | KEY_NUMERIC_C: "KEY_NUMERIC_C", 3461 | KEY_NUMERIC_D: "KEY_NUMERIC_D", 3462 | 3463 | KEY_CAMERA_FOCUS: "KEY_CAMERA_FOCUS", 3464 | KEY_WPS_BUTTON: "KEY_WPS_BUTTON", 3465 | 3466 | KEY_TOUCHPAD_TOGGLE: "KEY_TOUCHPAD_TOGGLE", 3467 | KEY_TOUCHPAD_ON: "KEY_TOUCHPAD_ON", 3468 | KEY_TOUCHPAD_OFF: "KEY_TOUCHPAD_OFF", 3469 | 3470 | KEY_CAMERA_ZOOMIN: "KEY_CAMERA_ZOOMIN", 3471 | KEY_CAMERA_ZOOMOUT: "KEY_CAMERA_ZOOMOUT", 3472 | KEY_CAMERA_UP: "KEY_CAMERA_UP", 3473 | KEY_CAMERA_DOWN: "KEY_CAMERA_DOWN", 3474 | KEY_CAMERA_LEFT: "KEY_CAMERA_LEFT", 3475 | KEY_CAMERA_RIGHT: "KEY_CAMERA_RIGHT", 3476 | 3477 | KEY_ATTENDANT_ON: "KEY_ATTENDANT_ON", 3478 | KEY_ATTENDANT_OFF: "KEY_ATTENDANT_OFF", 3479 | KEY_ATTENDANT_TOGGLE: "KEY_ATTENDANT_TOGGLE", 3480 | KEY_LIGHTS_TOGGLE: "KEY_LIGHTS_TOGGLE", 3481 | 3482 | BTN_DPAD_UP: "BTN_DPAD_UP", 3483 | BTN_DPAD_DOWN: "BTN_DPAD_DOWN", 3484 | BTN_DPAD_LEFT: "BTN_DPAD_LEFT", 3485 | BTN_DPAD_RIGHT: "BTN_DPAD_RIGHT", 3486 | 3487 | KEY_ALS_TOGGLE: "KEY_ALS_TOGGLE", 3488 | KEY_ROTATE_LOCK_TOGGLE: "KEY_ROTATE_LOCK_TOGGLE", 3489 | 3490 | KEY_BUTTONCONFIG: "KEY_BUTTONCONFIG", 3491 | KEY_TASKMANAGER: "KEY_TASKMANAGER", 3492 | KEY_JOURNAL: "KEY_JOURNAL", 3493 | KEY_CONTROLPANEL: "KEY_CONTROLPANEL", 3494 | KEY_APPSELECT: "KEY_APPSELECT", 3495 | KEY_SCREENSAVER: "KEY_SCREENSAVER", 3496 | KEY_VOICECOMMAND: "KEY_VOICECOMMAND", 3497 | KEY_ASSISTANT: "KEY_ASSISTANT", 3498 | KEY_KBD_LAYOUT_NEXT: "KEY_KBD_LAYOUT_NEXT", 3499 | KEY_EMOJI_PICKER: "KEY_EMOJI_PICKER", 3500 | KEY_DICTATE: "KEY_DICTATE", 3501 | KEY_CAMERA_ACCESS_ENABLE: "KEY_CAMERA_ACCESS_ENABLE", 3502 | KEY_CAMERA_ACCESS_DISABLE: "KEY_CAMERA_ACCESS_DISABLE", 3503 | KEY_CAMERA_ACCESS_TOGGLE: "KEY_CAMERA_ACCESS_TOGGLE", 3504 | 3505 | KEY_BRIGHTNESS_MIN: "KEY_BRIGHTNESS_MIN", 3506 | KEY_BRIGHTNESS_MAX: "KEY_BRIGHTNESS_MAX", 3507 | 3508 | KEY_KBDINPUTASSIST_PREV: "KEY_KBDINPUTASSIST_PREV", 3509 | KEY_KBDINPUTASSIST_NEXT: "KEY_KBDINPUTASSIST_NEXT", 3510 | KEY_KBDINPUTASSIST_PREVGROUP: "KEY_KBDINPUTASSIST_PREVGROUP", 3511 | KEY_KBDINPUTASSIST_NEXTGROUP: "KEY_KBDINPUTASSIST_NEXTGROUP", 3512 | KEY_KBDINPUTASSIST_ACCEPT: "KEY_KBDINPUTASSIST_ACCEPT", 3513 | KEY_KBDINPUTASSIST_CANCEL: "KEY_KBDINPUTASSIST_CANCEL", 3514 | 3515 | KEY_RIGHT_UP: "KEY_RIGHT_UP", 3516 | KEY_RIGHT_DOWN: "KEY_RIGHT_DOWN", 3517 | KEY_LEFT_UP: "KEY_LEFT_UP", 3518 | KEY_LEFT_DOWN: "KEY_LEFT_DOWN", 3519 | 3520 | KEY_ROOT_MENU: "KEY_ROOT_MENU", 3521 | 3522 | KEY_MEDIA_TOP_MENU: "KEY_MEDIA_TOP_MENU", 3523 | KEY_NUMERIC_11: "KEY_NUMERIC_11", 3524 | KEY_NUMERIC_12: "KEY_NUMERIC_12", 3525 | 3526 | KEY_AUDIO_DESC: "KEY_AUDIO_DESC", 3527 | KEY_3D_MODE: "KEY_3D_MODE", 3528 | KEY_NEXT_FAVORITE: "KEY_NEXT_FAVORITE", 3529 | KEY_STOP_RECORD: "KEY_STOP_RECORD", 3530 | KEY_PAUSE_RECORD: "KEY_PAUSE_RECORD", 3531 | KEY_VOD: "KEY_VOD", 3532 | KEY_UNMUTE: "KEY_UNMUTE", 3533 | KEY_FASTREVERSE: "KEY_FASTREVERSE", 3534 | KEY_SLOWREVERSE: "KEY_SLOWREVERSE", 3535 | 3536 | KEY_DATA: "KEY_DATA", 3537 | KEY_ONSCREEN_KEYBOARD: "KEY_ONSCREEN_KEYBOARD", 3538 | 3539 | KEY_PRIVACY_SCREEN_TOGGLE: "KEY_PRIVACY_SCREEN_TOGGLE", 3540 | 3541 | KEY_SELECTIVE_SCREENSHOT: "KEY_SELECTIVE_SCREENSHOT", 3542 | 3543 | KEY_NEXT_ELEMENT: "KEY_NEXT_ELEMENT", 3544 | KEY_PREVIOUS_ELEMENT: "KEY_PREVIOUS_ELEMENT", 3545 | 3546 | KEY_AUTOPILOT_ENGAGE_TOGGLE: "KEY_AUTOPILOT_ENGAGE_TOGGLE", 3547 | 3548 | KEY_MARK_WAYPOINT: "KEY_MARK_WAYPOINT", 3549 | KEY_SOS: "KEY_SOS", 3550 | KEY_NAV_CHART: "KEY_NAV_CHART", 3551 | KEY_FISHING_CHART: "KEY_FISHING_CHART", 3552 | KEY_SINGLE_RANGE_RADAR: "KEY_SINGLE_RANGE_RADAR", 3553 | KEY_DUAL_RANGE_RADAR: "KEY_DUAL_RANGE_RADAR", 3554 | KEY_RADAR_OVERLAY: "KEY_RADAR_OVERLAY", 3555 | KEY_TRADITIONAL_SONAR: "KEY_TRADITIONAL_SONAR", 3556 | KEY_CLEARVU_SONAR: "KEY_CLEARVU_SONAR", 3557 | KEY_SIDEVU_SONAR: "KEY_SIDEVU_SONAR", 3558 | KEY_NAV_INFO: "KEY_NAV_INFO", 3559 | KEY_BRIGHTNESS_MENU: "KEY_BRIGHTNESS_MENU", 3560 | 3561 | KEY_MACRO1: "KEY_MACRO1", 3562 | KEY_MACRO2: "KEY_MACRO2", 3563 | KEY_MACRO3: "KEY_MACRO3", 3564 | KEY_MACRO4: "KEY_MACRO4", 3565 | KEY_MACRO5: "KEY_MACRO5", 3566 | KEY_MACRO6: "KEY_MACRO6", 3567 | KEY_MACRO7: "KEY_MACRO7", 3568 | KEY_MACRO8: "KEY_MACRO8", 3569 | KEY_MACRO9: "KEY_MACRO9", 3570 | KEY_MACRO10: "KEY_MACRO10", 3571 | KEY_MACRO11: "KEY_MACRO11", 3572 | KEY_MACRO12: "KEY_MACRO12", 3573 | KEY_MACRO13: "KEY_MACRO13", 3574 | KEY_MACRO14: "KEY_MACRO14", 3575 | KEY_MACRO15: "KEY_MACRO15", 3576 | KEY_MACRO16: "KEY_MACRO16", 3577 | KEY_MACRO17: "KEY_MACRO17", 3578 | KEY_MACRO18: "KEY_MACRO18", 3579 | KEY_MACRO19: "KEY_MACRO19", 3580 | KEY_MACRO20: "KEY_MACRO20", 3581 | KEY_MACRO21: "KEY_MACRO21", 3582 | KEY_MACRO22: "KEY_MACRO22", 3583 | KEY_MACRO23: "KEY_MACRO23", 3584 | KEY_MACRO24: "KEY_MACRO24", 3585 | KEY_MACRO25: "KEY_MACRO25", 3586 | KEY_MACRO26: "KEY_MACRO26", 3587 | KEY_MACRO27: "KEY_MACRO27", 3588 | KEY_MACRO28: "KEY_MACRO28", 3589 | KEY_MACRO29: "KEY_MACRO29", 3590 | KEY_MACRO30: "KEY_MACRO30", 3591 | 3592 | KEY_MACRO_RECORD_START: "KEY_MACRO_RECORD_START", 3593 | KEY_MACRO_RECORD_STOP: "KEY_MACRO_RECORD_STOP", 3594 | KEY_MACRO_PRESET_CYCLE: "KEY_MACRO_PRESET_CYCLE", 3595 | KEY_MACRO_PRESET1: "KEY_MACRO_PRESET1", 3596 | KEY_MACRO_PRESET2: "KEY_MACRO_PRESET2", 3597 | KEY_MACRO_PRESET3: "KEY_MACRO_PRESET3", 3598 | 3599 | KEY_KBD_LCD_MENU1: "KEY_KBD_LCD_MENU1", 3600 | KEY_KBD_LCD_MENU2: "KEY_KBD_LCD_MENU2", 3601 | KEY_KBD_LCD_MENU3: "KEY_KBD_LCD_MENU3", 3602 | KEY_KBD_LCD_MENU4: "KEY_KBD_LCD_MENU4", 3603 | KEY_KBD_LCD_MENU5: "KEY_KBD_LCD_MENU5", 3604 | 3605 | BTN_TRIGGER_HAPPY: "BTN_TRIGGER_HAPPY/BTN_TRIGGER_HAPPY1", 3606 | BTN_TRIGGER_HAPPY2: "BTN_TRIGGER_HAPPY2", 3607 | BTN_TRIGGER_HAPPY3: "BTN_TRIGGER_HAPPY3", 3608 | BTN_TRIGGER_HAPPY4: "BTN_TRIGGER_HAPPY4", 3609 | BTN_TRIGGER_HAPPY5: "BTN_TRIGGER_HAPPY5", 3610 | BTN_TRIGGER_HAPPY6: "BTN_TRIGGER_HAPPY6", 3611 | BTN_TRIGGER_HAPPY7: "BTN_TRIGGER_HAPPY7", 3612 | BTN_TRIGGER_HAPPY8: "BTN_TRIGGER_HAPPY8", 3613 | BTN_TRIGGER_HAPPY9: "BTN_TRIGGER_HAPPY9", 3614 | BTN_TRIGGER_HAPPY10: "BTN_TRIGGER_HAPPY10", 3615 | BTN_TRIGGER_HAPPY11: "BTN_TRIGGER_HAPPY11", 3616 | BTN_TRIGGER_HAPPY12: "BTN_TRIGGER_HAPPY12", 3617 | BTN_TRIGGER_HAPPY13: "BTN_TRIGGER_HAPPY13", 3618 | BTN_TRIGGER_HAPPY14: "BTN_TRIGGER_HAPPY14", 3619 | BTN_TRIGGER_HAPPY15: "BTN_TRIGGER_HAPPY15", 3620 | BTN_TRIGGER_HAPPY16: "BTN_TRIGGER_HAPPY16", 3621 | BTN_TRIGGER_HAPPY17: "BTN_TRIGGER_HAPPY17", 3622 | BTN_TRIGGER_HAPPY18: "BTN_TRIGGER_HAPPY18", 3623 | BTN_TRIGGER_HAPPY19: "BTN_TRIGGER_HAPPY19", 3624 | BTN_TRIGGER_HAPPY20: "BTN_TRIGGER_HAPPY20", 3625 | BTN_TRIGGER_HAPPY21: "BTN_TRIGGER_HAPPY21", 3626 | BTN_TRIGGER_HAPPY22: "BTN_TRIGGER_HAPPY22", 3627 | BTN_TRIGGER_HAPPY23: "BTN_TRIGGER_HAPPY23", 3628 | BTN_TRIGGER_HAPPY24: "BTN_TRIGGER_HAPPY24", 3629 | BTN_TRIGGER_HAPPY25: "BTN_TRIGGER_HAPPY25", 3630 | BTN_TRIGGER_HAPPY26: "BTN_TRIGGER_HAPPY26", 3631 | BTN_TRIGGER_HAPPY27: "BTN_TRIGGER_HAPPY27", 3632 | BTN_TRIGGER_HAPPY28: "BTN_TRIGGER_HAPPY28", 3633 | BTN_TRIGGER_HAPPY29: "BTN_TRIGGER_HAPPY29", 3634 | BTN_TRIGGER_HAPPY30: "BTN_TRIGGER_HAPPY30", 3635 | BTN_TRIGGER_HAPPY31: "BTN_TRIGGER_HAPPY31", 3636 | BTN_TRIGGER_HAPPY32: "BTN_TRIGGER_HAPPY32", 3637 | BTN_TRIGGER_HAPPY33: "BTN_TRIGGER_HAPPY33", 3638 | BTN_TRIGGER_HAPPY34: "BTN_TRIGGER_HAPPY34", 3639 | BTN_TRIGGER_HAPPY35: "BTN_TRIGGER_HAPPY35", 3640 | BTN_TRIGGER_HAPPY36: "BTN_TRIGGER_HAPPY36", 3641 | BTN_TRIGGER_HAPPY37: "BTN_TRIGGER_HAPPY37", 3642 | BTN_TRIGGER_HAPPY38: "BTN_TRIGGER_HAPPY38", 3643 | BTN_TRIGGER_HAPPY39: "BTN_TRIGGER_HAPPY39", 3644 | BTN_TRIGGER_HAPPY40: "BTN_TRIGGER_HAPPY40", 3645 | 3646 | KEY_MAX: "KEY_MAX", 3647 | KEY_CNT: "KEY_CNT", 3648 | } 3649 | 3650 | var RELNames = map[EvCode]string{ 3651 | REL_X: "REL_X", 3652 | REL_Y: "REL_Y", 3653 | REL_Z: "REL_Z", 3654 | REL_RX: "REL_RX", 3655 | REL_RY: "REL_RY", 3656 | REL_RZ: "REL_RZ", 3657 | REL_HWHEEL: "REL_HWHEEL", 3658 | REL_DIAL: "REL_DIAL", 3659 | REL_WHEEL: "REL_WHEEL", 3660 | REL_MISC: "REL_MISC", 3661 | 3662 | REL_RESERVED: "REL_RESERVED", 3663 | REL_WHEEL_HI_RES: "REL_WHEEL_HI_RES", 3664 | REL_HWHEEL_HI_RES: "REL_HWHEEL_HI_RES", 3665 | REL_MAX: "REL_MAX", 3666 | REL_CNT: "REL_CNT", 3667 | } 3668 | 3669 | var ABSNames = map[EvCode]string{ 3670 | ABS_X: "ABS_X", 3671 | ABS_Y: "ABS_Y", 3672 | ABS_Z: "ABS_Z", 3673 | ABS_RX: "ABS_RX", 3674 | ABS_RY: "ABS_RY", 3675 | ABS_RZ: "ABS_RZ", 3676 | ABS_THROTTLE: "ABS_THROTTLE", 3677 | ABS_RUDDER: "ABS_RUDDER", 3678 | ABS_WHEEL: "ABS_WHEEL", 3679 | ABS_GAS: "ABS_GAS", 3680 | ABS_BRAKE: "ABS_BRAKE", 3681 | ABS_HAT0X: "ABS_HAT0X", 3682 | ABS_HAT0Y: "ABS_HAT0Y", 3683 | ABS_HAT1X: "ABS_HAT1X", 3684 | ABS_HAT1Y: "ABS_HAT1Y", 3685 | ABS_HAT2X: "ABS_HAT2X", 3686 | ABS_HAT2Y: "ABS_HAT2Y", 3687 | ABS_HAT3X: "ABS_HAT3X", 3688 | ABS_HAT3Y: "ABS_HAT3Y", 3689 | ABS_PRESSURE: "ABS_PRESSURE", 3690 | ABS_DISTANCE: "ABS_DISTANCE", 3691 | ABS_TILT_X: "ABS_TILT_X", 3692 | ABS_TILT_Y: "ABS_TILT_Y", 3693 | ABS_TOOL_WIDTH: "ABS_TOOL_WIDTH", 3694 | 3695 | ABS_VOLUME: "ABS_VOLUME", 3696 | ABS_PROFILE: "ABS_PROFILE", 3697 | 3698 | ABS_MISC: "ABS_MISC", 3699 | 3700 | ABS_RESERVED: "ABS_RESERVED", 3701 | 3702 | ABS_MT_SLOT: "ABS_MT_SLOT", 3703 | ABS_MT_TOUCH_MAJOR: "ABS_MT_TOUCH_MAJOR", 3704 | ABS_MT_TOUCH_MINOR: "ABS_MT_TOUCH_MINOR", 3705 | ABS_MT_WIDTH_MAJOR: "ABS_MT_WIDTH_MAJOR", 3706 | ABS_MT_WIDTH_MINOR: "ABS_MT_WIDTH_MINOR", 3707 | ABS_MT_ORIENTATION: "ABS_MT_ORIENTATION", 3708 | ABS_MT_POSITION_X: "ABS_MT_POSITION_X", 3709 | ABS_MT_POSITION_Y: "ABS_MT_POSITION_Y", 3710 | ABS_MT_TOOL_TYPE: "ABS_MT_TOOL_TYPE", 3711 | ABS_MT_BLOB_ID: "ABS_MT_BLOB_ID", 3712 | ABS_MT_TRACKING_ID: "ABS_MT_TRACKING_ID", 3713 | ABS_MT_PRESSURE: "ABS_MT_PRESSURE", 3714 | ABS_MT_DISTANCE: "ABS_MT_DISTANCE", 3715 | ABS_MT_TOOL_X: "ABS_MT_TOOL_X", 3716 | ABS_MT_TOOL_Y: "ABS_MT_TOOL_Y", 3717 | 3718 | ABS_MAX: "ABS_MAX", 3719 | ABS_CNT: "ABS_CNT", 3720 | } 3721 | 3722 | var SWNames = map[EvCode]string{ 3723 | SW_LID: "SW_LID", 3724 | SW_TABLET_MODE: "SW_TABLET_MODE", 3725 | SW_HEADPHONE_INSERT: "SW_HEADPHONE_INSERT", 3726 | SW_RFKILL_ALL: "SW_RFKILL_ALL/SW_RADIO", 3727 | SW_MICROPHONE_INSERT: "SW_MICROPHONE_INSERT", 3728 | SW_DOCK: "SW_DOCK", 3729 | SW_LINEOUT_INSERT: "SW_LINEOUT_INSERT", 3730 | SW_JACK_PHYSICAL_INSERT: "SW_JACK_PHYSICAL_INSERT", 3731 | SW_VIDEOOUT_INSERT: "SW_VIDEOOUT_INSERT", 3732 | SW_CAMERA_LENS_COVER: "SW_CAMERA_LENS_COVER", 3733 | SW_KEYPAD_SLIDE: "SW_KEYPAD_SLIDE", 3734 | SW_FRONT_PROXIMITY: "SW_FRONT_PROXIMITY", 3735 | SW_ROTATE_LOCK: "SW_ROTATE_LOCK", 3736 | SW_LINEIN_INSERT: "SW_LINEIN_INSERT", 3737 | SW_MUTE_DEVICE: "SW_MUTE_DEVICE", 3738 | SW_PEN_INSERTED: "SW_PEN_INSERTED", 3739 | SW_MACHINE_COVER: "SW_MACHINE_COVER/SW_MAX", 3740 | SW_CNT: "SW_CNT", 3741 | } 3742 | 3743 | var MSCNames = map[EvCode]string{ 3744 | MSC_SERIAL: "MSC_SERIAL", 3745 | MSC_PULSELED: "MSC_PULSELED", 3746 | MSC_GESTURE: "MSC_GESTURE", 3747 | MSC_RAW: "MSC_RAW", 3748 | MSC_SCAN: "MSC_SCAN", 3749 | MSC_TIMESTAMP: "MSC_TIMESTAMP", 3750 | MSC_MAX: "MSC_MAX", 3751 | MSC_CNT: "MSC_CNT", 3752 | } 3753 | 3754 | var LEDNames = map[EvCode]string{ 3755 | LED_NUML: "LED_NUML", 3756 | LED_CAPSL: "LED_CAPSL", 3757 | LED_SCROLLL: "LED_SCROLLL", 3758 | LED_COMPOSE: "LED_COMPOSE", 3759 | LED_KANA: "LED_KANA", 3760 | LED_SLEEP: "LED_SLEEP", 3761 | LED_SUSPEND: "LED_SUSPEND", 3762 | LED_MUTE: "LED_MUTE", 3763 | LED_MISC: "LED_MISC", 3764 | LED_MAIL: "LED_MAIL", 3765 | LED_CHARGING: "LED_CHARGING", 3766 | LED_MAX: "LED_MAX", 3767 | LED_CNT: "LED_CNT", 3768 | } 3769 | 3770 | var REPNames = map[EvCode]string{ 3771 | REP_DELAY: "REP_DELAY", 3772 | REP_PERIOD: "REP_PERIOD/REP_MAX", 3773 | REP_CNT: "REP_CNT", 3774 | } 3775 | 3776 | var SNDNames = map[EvCode]string{ 3777 | SND_CLICK: "SND_CLICK", 3778 | SND_BELL: "SND_BELL", 3779 | SND_TONE: "SND_TONE", 3780 | SND_MAX: "SND_MAX", 3781 | SND_CNT: "SND_CNT", 3782 | } 3783 | 3784 | var IDNames = map[EvCode]string{ 3785 | ID_BUS: "ID_BUS", 3786 | ID_VENDOR: "ID_VENDOR", 3787 | ID_PRODUCT: "ID_PRODUCT", 3788 | ID_VERSION: "ID_VERSION", 3789 | } 3790 | 3791 | var BUSNames = map[EvCode]string{ 3792 | BUS_PCI: "BUS_PCI", 3793 | BUS_ISAPNP: "BUS_ISAPNP", 3794 | BUS_USB: "BUS_USB", 3795 | BUS_HIL: "BUS_HIL", 3796 | BUS_BLUETOOTH: "BUS_BLUETOOTH", 3797 | BUS_VIRTUAL: "BUS_VIRTUAL", 3798 | 3799 | BUS_ISA: "BUS_ISA", 3800 | BUS_I8042: "BUS_I8042", 3801 | BUS_XTKBD: "BUS_XTKBD", 3802 | BUS_RS232: "BUS_RS232", 3803 | BUS_GAMEPORT: "BUS_GAMEPORT", 3804 | BUS_PARPORT: "BUS_PARPORT", 3805 | BUS_AMIGA: "BUS_AMIGA", 3806 | BUS_ADB: "BUS_ADB", 3807 | BUS_I2C: "BUS_I2C", 3808 | BUS_HOST: "BUS_HOST", 3809 | BUS_GSC: "BUS_GSC", 3810 | BUS_ATARI: "BUS_ATARI", 3811 | BUS_SPI: "BUS_SPI", 3812 | BUS_RMI: "BUS_RMI", 3813 | BUS_CEC: "BUS_CEC", 3814 | BUS_INTEL_ISHTP: "BUS_INTEL_ISHTP", 3815 | BUS_AMD_SFH: "BUS_AMD_SFH", 3816 | } 3817 | 3818 | var MTNames = map[EvCode]string{ 3819 | MT_TOOL_FINGER: "MT_TOOL_FINGER", 3820 | MT_TOOL_PEN: "MT_TOOL_PEN", 3821 | MT_TOOL_PALM: "MT_TOOL_PALM", 3822 | MT_TOOL_DIAL: "MT_TOOL_DIAL", 3823 | MT_TOOL_MAX: "MT_TOOL_MAX", 3824 | } 3825 | 3826 | var FFNames = map[EvCode]string{ 3827 | FF_STATUS_STOPPED: "FF_STATUS_STOPPED", 3828 | FF_STATUS_PLAYING: "FF_STATUS_PLAYING/FF_STATUS_MAX", 3829 | 3830 | FF_RUMBLE: "FF_RUMBLE/FF_EFFECT_MIN", 3831 | FF_PERIODIC: "FF_PERIODIC", 3832 | FF_CONSTANT: "FF_CONSTANT", 3833 | FF_SPRING: "FF_SPRING", 3834 | FF_FRICTION: "FF_FRICTION", 3835 | FF_DAMPER: "FF_DAMPER", 3836 | FF_INERTIA: "FF_INERTIA", 3837 | FF_RAMP: "FF_RAMP/FF_EFFECT_MAX", 3838 | 3839 | FF_SQUARE: "FF_SQUARE/FF_WAVEFORM_MIN", 3840 | FF_TRIANGLE: "FF_TRIANGLE", 3841 | FF_SINE: "FF_SINE", 3842 | FF_SAW_UP: "FF_SAW_UP", 3843 | FF_SAW_DOWN: "FF_SAW_DOWN", 3844 | FF_CUSTOM: "FF_CUSTOM/FF_WAVEFORM_MAX", 3845 | 3846 | FF_GAIN: "FF_GAIN/FF_MAX_EFFECTS", 3847 | FF_AUTOCENTER: "FF_AUTOCENTER", 3848 | 3849 | FF_MAX: "FF_MAX", 3850 | FF_CNT: "FF_CNT", 3851 | } 3852 | -------------------------------------------------------------------------------- /device.go: -------------------------------------------------------------------------------- 1 | package evdev 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | "os" 7 | "syscall" 8 | ) 9 | 10 | // InputDevice represent a Linux kernel input device in userspace. 11 | // It can be used to query and write device properties, read input events, 12 | // or grab it for exclusive access. 13 | type InputDevice struct { 14 | file *os.File 15 | driverVersion int32 16 | } 17 | 18 | // OpenWithFlags creates a new InputDevice from the given path. The input device 19 | // is opened with the specified flags (O_RDONLY etc.). 20 | // It is the responsibility of the user to provide sane flags and handle potential errors 21 | // resulting from inappropriate flag combinations or permissions. 22 | // Returns an error if the device node could not be opened or its properties failed to read. 23 | func OpenWithFlags(path string, flags int) (*InputDevice, error) { 24 | d := &InputDevice{} 25 | 26 | var err error 27 | d.file, err = os.OpenFile(path, flags, 0) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | d.driverVersion, err = ioctlEVIOCGVERSION(d.file.Fd()) 33 | if err != nil { 34 | _ = d.file.Close() 35 | return nil, fmt.Errorf("cannot get driver version: %v", err) 36 | } 37 | 38 | return d, nil 39 | } 40 | 41 | // Open creates a new InputDevice from the given path. The input device is 42 | // opened with flag O_RDWR. Returns an error if the device node could not 43 | // be opened or its properties failed to read. 44 | func Open(path string) (*InputDevice, error) { 45 | return OpenWithFlags(path, os.O_RDWR) 46 | } 47 | 48 | // OpenByNameWithFlags creates a new InputDevice from the device name as reported 49 | // by the kernel. The input device is opened with the specified flags (O_RDONLY etc.). 50 | // It is the responsibility of the user to provide sane flags and handle potential errors 51 | // resulting from inappropriate flag combinations or permissions. 52 | // Returns an error if the name does not exist, or the device node could 53 | // not be opened or its properties failed to read. 54 | func OpenByNameWithFlags(name string, flags int) (*InputDevice, error) { 55 | devices, err := ListDevicePaths() 56 | if err != nil { 57 | return nil, err 58 | } 59 | for _, d := range devices { 60 | if d.Name == name { 61 | return OpenWithFlags(d.Path, flags) 62 | } 63 | } 64 | return nil, fmt.Errorf("could not find input device with name %q", name) 65 | } 66 | 67 | // OpenByName creates a new InputDevice from the device name as reported by the kernel. 68 | // The input device is opened with flag O_RDWR. 69 | // Returns an error if the name does not exist, or the device node could 70 | // not be opened or its properties failed to read. 71 | func OpenByName(name string) (*InputDevice, error) { 72 | return OpenByNameWithFlags(name, os.O_RDWR) 73 | } 74 | 75 | // Close releases the resources held by an InputDevice. After calling this 76 | // function, the InputDevice is no longer operational. 77 | func (d *InputDevice) Close() error { 78 | return d.file.Close() 79 | } 80 | 81 | // Path returns the device's node path it was opened under. 82 | func (d *InputDevice) Path() string { 83 | return d.file.Name() 84 | } 85 | 86 | // DriverVersion returns the version of the Linux Evdev driver. 87 | // The three ints returned by this function describe the major, minor and 88 | // micro parts of the version code. 89 | func (d *InputDevice) DriverVersion() (int, int, int) { 90 | return int(d.driverVersion >> 16), 91 | int((d.driverVersion >> 8) & 0xff), 92 | int((d.driverVersion >> 0) & 0xff) 93 | } 94 | 95 | // Name returns the device's name as reported by the kernel. 96 | func (d *InputDevice) Name() (string, error) { 97 | return ioctlEVIOCGNAME(d.file.Fd()) 98 | } 99 | 100 | // PhysicalLocation returns the device's physical location as reported by the kernel. 101 | func (d *InputDevice) PhysicalLocation() (string, error) { 102 | return ioctlEVIOCGPHYS(d.file.Fd()) 103 | } 104 | 105 | // UniqueID returns the device's unique identifier as reported by the kernel. 106 | func (d *InputDevice) UniqueID() (string, error) { 107 | return ioctlEVIOCGUNIQ(d.file.Fd()) 108 | } 109 | 110 | // InputID returns the device's vendor/product/busType/version information as reported by the kernel. 111 | func (d *InputDevice) InputID() (InputID, error) { 112 | return ioctlEVIOCGID(d.file.Fd()) 113 | } 114 | 115 | // CapableTypes returns a slice of EvType that are the device supports 116 | func (d *InputDevice) CapableTypes() []EvType { 117 | var types []EvType 118 | 119 | evBits, err := ioctlEVIOCGBIT(d.file.Fd(), 0) 120 | if err != nil { 121 | return []EvType{} 122 | } 123 | 124 | evBitmap := newBitmap(evBits) 125 | 126 | for _, t := range evBitmap.setBits() { 127 | types = append(types, EvType(t)) 128 | } 129 | 130 | return types 131 | } 132 | 133 | // CapableEvents returns a slice of EvCode that are the device supports for given EvType 134 | func (d *InputDevice) CapableEvents(t EvType) []EvCode { 135 | var codes []EvCode 136 | 137 | evBits, err := ioctlEVIOCGBIT(d.file.Fd(), int(t)) 138 | if err != nil { 139 | return []EvCode{} 140 | } 141 | 142 | evBitmap := newBitmap(evBits) 143 | 144 | for _, t := range evBitmap.setBits() { 145 | codes = append(codes, EvCode(t)) 146 | } 147 | 148 | return codes 149 | } 150 | 151 | // Properties returns a slice of EvProp that are the device supports 152 | func (d *InputDevice) Properties() []EvProp { 153 | var props []EvProp 154 | 155 | propBits, err := ioctlEVIOCGPROP(d.file.Fd()) 156 | if err != nil { 157 | return []EvProp{} 158 | } 159 | 160 | propBitmap := newBitmap(propBits) 161 | 162 | for _, p := range propBitmap.setBits() { 163 | props = append(props, EvProp(p)) 164 | } 165 | 166 | return props 167 | } 168 | 169 | // State return a StateMap for the given type. The map will be empty if the requested type 170 | // is not supported by the device. 171 | func (d *InputDevice) State(t EvType) (StateMap, error) { 172 | fd := d.file.Fd() 173 | 174 | evBits, err := ioctlEVIOCGBIT(fd, 0) 175 | if err != nil { 176 | return nil, fmt.Errorf("cannot get evBits: %v", err) 177 | } 178 | 179 | evBitmap := newBitmap(evBits) 180 | 181 | if !evBitmap.bitIsSet(int(t)) { 182 | return StateMap{}, nil 183 | } 184 | 185 | codeBits, err := ioctlEVIOCGBIT(fd, int(t)) 186 | if err != nil { 187 | return nil, fmt.Errorf("cannot get evBits: %v", err) 188 | } 189 | 190 | codeBitmap := newBitmap(codeBits) 191 | 192 | var stateBits []byte 193 | 194 | switch t { 195 | case EV_KEY: 196 | stateBits, err = ioctlEVIOCGKEY(fd) 197 | case EV_SW: 198 | stateBits, err = ioctlEVIOCGSW(fd) 199 | case EV_LED: 200 | stateBits, err = ioctlEVIOCGLED(fd) 201 | case EV_SND: 202 | stateBits, err = ioctlEVIOCGSND(fd) 203 | default: 204 | err = fmt.Errorf("unsupported evType %d", t) 205 | } 206 | 207 | if err != nil { 208 | return nil, err 209 | } 210 | 211 | stateBitmap := newBitmap(stateBits) 212 | st := StateMap{} 213 | 214 | for _, code := range codeBitmap.setBits() { 215 | st[EvCode(code)] = stateBitmap.bitIsSet(code) 216 | } 217 | 218 | return st, nil 219 | } 220 | 221 | // AbsInfos returns the AbsInfo struct for all axis the device supports. 222 | func (d *InputDevice) AbsInfos() (map[EvCode]AbsInfo, error) { 223 | a := make(map[EvCode]AbsInfo) 224 | 225 | absBits, err := ioctlEVIOCGBIT(d.file.Fd(), EV_ABS) 226 | if err != nil { 227 | return nil, fmt.Errorf("cannot get absBits: %v", err) 228 | } 229 | 230 | absBitmap := newBitmap(absBits) 231 | 232 | for _, abs := range absBitmap.setBits() { 233 | absInfo, err := ioctlEVIOCGABS(d.file.Fd(), abs) 234 | if err == nil { 235 | a[EvCode(abs)] = absInfo 236 | } 237 | } 238 | 239 | return a, nil 240 | } 241 | 242 | // Grab grabs the device for exclusive access. No other process will receive 243 | // input events until the device instance is active. 244 | func (d *InputDevice) Grab() error { 245 | return ioctlEVIOCGRAB(d.file.Fd(), 1) 246 | } 247 | 248 | // Ungrab releases a previously taken exclusive use with Grab(). 249 | func (d *InputDevice) Ungrab() error { 250 | return ioctlEVIOCGRAB(d.file.Fd(), 0) 251 | } 252 | 253 | // Revoke revokes device access 254 | func (d *InputDevice) Revoke() error { 255 | return ioctlEVIOCREVOKE(d.file.Fd()) 256 | } 257 | 258 | // NonBlock sets file descriptor into nonblocking mode. 259 | // This way it is possible to interrupt ReadOne call by closing the device. 260 | // Note: file.Fd() call will set file descriptor back to blocking mode so make sure your program 261 | // is not using any other method than ReadOne after NonBlock call. 262 | func (d *InputDevice) NonBlock() error { 263 | return syscall.SetNonblock(int(d.file.Fd()), true) 264 | } 265 | 266 | // ReadOne reads one InputEvent from the device. It blocks until an event has 267 | // been received or an error has occurred. 268 | func (d *InputDevice) ReadOne() (*InputEvent, error) { 269 | event := InputEvent{} 270 | 271 | err := binary.Read(d.file, binary.LittleEndian, &event) 272 | if err != nil { 273 | return nil, err 274 | } 275 | 276 | return &event, nil 277 | } 278 | 279 | // WriteOne writes one InputEvent to the device. 280 | // Useful for controlling LEDs of the device 281 | func (d *InputDevice) WriteOne(event *InputEvent) error { 282 | return binary.Write(d.file, binary.LittleEndian, event) 283 | } 284 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/holoplot/go-evdev 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /ioctl.go: -------------------------------------------------------------------------------- 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 | } 275 | -------------------------------------------------------------------------------- /list.go: -------------------------------------------------------------------------------- 1 | package evdev 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | // InputPath contains information about an InputDevice Name & Path 9 | type InputPath struct { 10 | Name string 11 | Path string 12 | } 13 | 14 | // ListDevicePaths lists all available input devices, returning their 15 | // filename path, and the name as reported by the kernel. 16 | func ListDevicePaths() ([]InputPath, error) { 17 | var list []InputPath 18 | 19 | basePath := "/dev/input" 20 | 21 | files, err := os.ReadDir(basePath) 22 | if err != nil { 23 | return list, err 24 | } 25 | 26 | for _, fileName := range files { 27 | if fileName.IsDir() { 28 | continue 29 | } 30 | 31 | full := fmt.Sprintf("%s/%s", basePath, fileName.Name()) 32 | if d, err := OpenWithFlags(full, os.O_RDONLY); err == nil { 33 | name, _ := d.Name() 34 | list = append(list, InputPath{Name: name, Path: d.Path()}) 35 | d.Close() 36 | } 37 | } 38 | return list, nil 39 | } 40 | -------------------------------------------------------------------------------- /names.go: -------------------------------------------------------------------------------- 1 | package evdev 2 | 3 | var EvCodeNameLookup = map[EvType]map[EvCode]string{ 4 | EV_SYN: SYNNames, 5 | EV_KEY: KEYNames, 6 | EV_REL: RELNames, 7 | EV_ABS: ABSNames, 8 | EV_MSC: MSCNames, 9 | EV_SW: SWNames, 10 | EV_LED: LEDNames, 11 | EV_SND: SNDNames, 12 | EV_REP: REPNames, 13 | EV_FF: FFNames, 14 | // EV_PWR: 15 | // EV_FF_STATUS: 16 | } 17 | 18 | // TypeName returns the name of an EvType as string, or "UNKNOWN" if the type is not valid 19 | func TypeName(t EvType) string { 20 | name, ok := EVToString[t] 21 | if ok { 22 | return name 23 | } 24 | return "unknown" 25 | } 26 | 27 | // PropName returns the name of the given EvProp, or "UNKNOWN" if the property is not valid 28 | func PropName(p EvProp) string { 29 | name, ok := INPUTToString[p] 30 | if ok { 31 | return name 32 | } 33 | return "unknown" 34 | } 35 | 36 | // CodeName returns the name of an EvfCode in the given EvType, or "UNKNOWN" of the code is not valid. 37 | func CodeName(t EvType, c EvCode) string { 38 | name, ok := EvCodeNameLookup[t][c] 39 | if !ok { 40 | return "unknown" 41 | } 42 | return name 43 | } 44 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | package evdev 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | ) 7 | 8 | // EvType is EV_KEY, EV_SW, EV_LED, EV_SND, ... 9 | type EvType uint16 10 | 11 | // EvCode describes codes within a type (eg. KEY_A, KEY_B, ...) 12 | type EvCode uint16 13 | 14 | // EvProp describes device properties (eg. INPUT_PROP_ACCELEROMETER, INPUT_PROP_BUTTONPAD, ...) 15 | type EvProp uint16 16 | 17 | // StateMap describes the current state of codes within a type, as booleans. 18 | type StateMap map[EvCode]bool 19 | 20 | // InputEvent describes an event that is generated by an InputDevice 21 | type InputEvent struct { 22 | Time syscall.Timeval // time in seconds since epoch at which event occurred 23 | Type EvType // event type - one of ecodes.EV_* 24 | Code EvCode // event code related to the event type 25 | Value int32 // event value related to the event type 26 | } 27 | 28 | func (e *InputEvent) TypeName() string { 29 | return TypeName(e.Type) 30 | } 31 | 32 | func (e *InputEvent) CodeName() string { 33 | return CodeName(e.Type, e.Code) 34 | } 35 | 36 | func (e *InputEvent) String() string { 37 | return fmt.Sprintf( 38 | "type: 0x%02x [%s], code: 0x%02x [%s], value: %d", 39 | e.Type, e.TypeName(), e.Code, e.CodeName(), e.Value, 40 | ) 41 | } 42 | 43 | // InputID ... 44 | type InputID struct { 45 | BusType uint16 46 | Vendor uint16 47 | Product uint16 48 | Version uint16 49 | } 50 | 51 | // AbsInfo describes details on ABS input types 52 | type AbsInfo struct { 53 | Value int32 54 | Minimum int32 55 | Maximum int32 56 | Fuzz int32 57 | Flat int32 58 | Resolution int32 59 | } 60 | 61 | // InputKeymapEntry is used to retrieve and modify keymap data 62 | type InputKeymapEntry struct { 63 | Flags uint8 64 | Len uint8 65 | Index uint16 66 | KeyCode uint32 67 | ScanCode [32]uint8 68 | } 69 | 70 | // InputMask ... 71 | type InputMask struct { 72 | Type uint32 73 | CodesSize uint32 74 | CodesPtr uint64 75 | } 76 | 77 | // UinputUserDevice is used when creating or cloning a device 78 | type UinputUserDevice struct { 79 | Name [uinputMaxNameSize]byte 80 | ID InputID 81 | EffectsMax uint32 82 | Absmax [absSize]int32 83 | Absmin [absSize]int32 84 | Absfuzz [absSize]int32 85 | Absflat [absSize]int32 86 | } 87 | -------------------------------------------------------------------------------- /uinput.go: -------------------------------------------------------------------------------- 1 | package evdev 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | "os" 8 | "syscall" 9 | ) 10 | 11 | const ( 12 | uinputMaxNameSize = 80 13 | absSize = 64 14 | ) 15 | 16 | // CreateDevice creates a device from scratch with the provided capabilities and name 17 | // If set up fails the device will be removed from the system, 18 | // once set up it can be removed by calling dev.Close 19 | func CreateDevice(name string, id InputID, capabilities map[EvType][]EvCode) (*InputDevice, error) { 20 | deviceFile, err := os.OpenFile("/dev/uinput", syscall.O_WRONLY|syscall.O_NONBLOCK, 0660) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | newDev := &InputDevice{ 26 | file: deviceFile, 27 | } 28 | 29 | for ev, codes := range capabilities { 30 | if err := ioctlUISETEVBIT(newDev.file.Fd(), uintptr(ev)); err != nil { 31 | DestroyDevice(newDev) 32 | return nil, fmt.Errorf("failed to set ev bit: %d - %w", ev, err) 33 | } 34 | 35 | if err := setEventCodes(newDev, ev, codes); err != nil { 36 | DestroyDevice(newDev) 37 | return nil, fmt.Errorf("failed to set ev code: %w", err) 38 | } 39 | } 40 | 41 | if _, err = createInputDevice(newDev.file, UinputUserDevice{ 42 | Name: toUinputName([]byte(name)), 43 | ID: id, 44 | }); err != nil { 45 | DestroyDevice(newDev) 46 | return nil, fmt.Errorf("failed to create device: %w", err) 47 | } 48 | 49 | return newDev, nil 50 | } 51 | 52 | // CloneDevice creates a new device from an existing one 53 | // all capabilites will be coppied over to the new virtual device 54 | // If set up fails the device will be removed from the system, 55 | // once set up it can be removed by calling dev.Close 56 | func CloneDevice(name string, dev *InputDevice) (*InputDevice, error) { 57 | deviceFile, err := os.OpenFile("/dev/uinput", syscall.O_WRONLY|syscall.O_NONBLOCK, 0660) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | newDev := &InputDevice{ 63 | file: deviceFile, 64 | driverVersion: dev.driverVersion, 65 | } 66 | 67 | for _, ev := range dev.CapableTypes() { 68 | if err := ioctlUISETEVBIT(newDev.file.Fd(), uintptr(ev)); err != nil { 69 | DestroyDevice(newDev) 70 | return nil, fmt.Errorf("failed to set ev bit: %d - %w", ev, err) 71 | } 72 | 73 | eventCodes := dev.CapableEvents(ev) 74 | if err := setEventCodes(newDev, ev, eventCodes); err != nil { 75 | DestroyDevice(newDev) 76 | return nil, fmt.Errorf("failed to set ev code: %w", err) 77 | } 78 | } 79 | 80 | id, err := dev.InputID() 81 | if err != nil { 82 | DestroyDevice(newDev) 83 | return nil, fmt.Errorf("failed to get original device id: %w", err) 84 | } 85 | 86 | if _, err = createInputDevice(newDev.file, UinputUserDevice{ 87 | Name: toUinputName([]byte(name)), 88 | ID: id, 89 | }); err != nil { 90 | return nil, fmt.Errorf("failed to create device: %w", err) 91 | } 92 | 93 | return newDev, nil 94 | } 95 | 96 | // Destroy destroys an input device, removing it from the system 97 | // This is designed to be called on self created virtual devices and may fail if called 98 | // on real devices attached to the system 99 | func DestroyDevice(dev *InputDevice) error { 100 | return ioctlUIDEVDESTROY(dev.file.Fd()) 101 | } 102 | 103 | func setEventCodes(dev *InputDevice, ev EvType, codes []EvCode) error { 104 | for _, code := range codes { 105 | var err error 106 | 107 | switch ev { 108 | case EV_ABS: 109 | err = ioctlUISETABSBIT(dev.file.Fd(), uintptr(code)) 110 | case EV_FF: 111 | err = ioctlUISETFFBIT(dev.file.Fd(), uintptr(code)) 112 | case EV_KEY: 113 | err = ioctlUISETKEYBIT(dev.file.Fd(), uintptr(code)) 114 | case EV_LED: 115 | err = ioctlUISETLEDBIT(dev.file.Fd(), uintptr(code)) 116 | case EV_MSC: 117 | err = ioctlUISETMSCBIT(dev.file.Fd(), uintptr(code)) 118 | case EV_REL: 119 | err = ioctlUISETRELBIT(dev.file.Fd(), uintptr(code)) 120 | case EV_SND: 121 | err = ioctlUISETSNDBIT(dev.file.Fd(), uintptr(code)) 122 | case EV_SW: 123 | err = ioctlUISETSWBIT(dev.file.Fd(), uintptr(code)) 124 | } 125 | 126 | if err != nil { 127 | return err 128 | } 129 | } 130 | 131 | return nil 132 | } 133 | 134 | func toUinputName(name []byte) (uinputName [uinputMaxNameSize]byte) { 135 | var fixedSizeName [uinputMaxNameSize]byte 136 | copy(fixedSizeName[:], name) 137 | 138 | return fixedSizeName 139 | } 140 | 141 | func createInputDevice(file *os.File, dev UinputUserDevice) (fd *os.File, err error) { 142 | buf := new(bytes.Buffer) 143 | 144 | if err = binary.Write(buf, binary.LittleEndian, dev); err != nil { 145 | file.Close() 146 | return nil, fmt.Errorf("failed to write user device buffer: %w", err) 147 | } 148 | 149 | if _, err = file.Write(buf.Bytes()); err != nil { 150 | file.Close() 151 | return nil, fmt.Errorf("failed to write uidev struct to device file: %w", err) 152 | } 153 | 154 | if err = ioctlUIDEVCREATE(file.Fd()); err != nil { 155 | file.Close() 156 | return nil, fmt.Errorf("failed to create device: %w", err) 157 | } 158 | 159 | return file, nil 160 | } 161 | --------------------------------------------------------------------------------