• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
4  */
5 
6 #include "config.h"
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <strings.h>
11 
12 #include "libevdev-int.h"
13 #include "libevdev-util.h"
14 #include "libevdev.h"
15 
16 #include "event-names.h"
17 
18 struct name_lookup {
19 	const char *name;
20 	size_t len;
21 };
22 
cmp_entry(const void * vlookup,const void * ventry)23 static int cmp_entry(const void *vlookup, const void *ventry)
24 {
25 	const struct name_lookup *lookup = vlookup;
26 	const struct name_entry *entry = ventry;
27 	int r;
28 
29 	r = strncmp(lookup->name, entry->name, lookup->len);
30 	if (!r) {
31 		if (entry->name[lookup->len])
32 			r = -1;
33 		else
34 			r = 0;
35 	}
36 
37 	return r;
38 }
39 
40 static const struct name_entry*
lookup_name(const struct name_entry * array,size_t asize,struct name_lookup * lookup)41 lookup_name(const struct name_entry *array, size_t asize,
42 	    struct name_lookup *lookup)
43 {
44 	const struct name_entry *entry;
45 
46 	entry = bsearch(lookup, array, asize, sizeof(*array), cmp_entry);
47 	if (!entry)
48 		return NULL;
49 
50 	return entry;
51 }
52 
53 LIBEVDEV_EXPORT int
libevdev_event_type_from_name(const char * name)54 libevdev_event_type_from_name(const char *name)
55 {
56 	return libevdev_event_type_from_name_n(name, strlen(name));
57 }
58 
59 LIBEVDEV_EXPORT int
libevdev_event_type_from_name_n(const char * name,size_t len)60 libevdev_event_type_from_name_n(const char *name, size_t len)
61 {
62 	struct name_lookup lookup;
63 	const struct name_entry *entry;
64 
65 	lookup.name = name;
66 	lookup.len = len;
67 
68 	entry = lookup_name(ev_names, ARRAY_LENGTH(ev_names), &lookup);
69 
70 	return entry ? (int)entry->value : -1;
71 }
72 
type_from_prefix(const char * name,ssize_t len)73 static int type_from_prefix(const char *name, ssize_t len)
74 {
75 	const char *e;
76 	size_t i;
77 	ssize_t l;
78 
79 	/* MAX_ is not allowed, even though EV_MAX exists */
80 	if (startswith(name, len, "MAX_", 4))
81 		return -1;
82 	/* BTN_ is special as there is no EV_BTN type */
83 	if (startswith(name, len, "BTN_", 4))
84 		return EV_KEY;
85 	/* FF_STATUS_ is special as FF_ is a prefix of it, so test it first */
86 	if (startswith(name, len, "FF_STATUS_", 10))
87 		return EV_FF_STATUS;
88 
89 	for (i = 0; i < ARRAY_LENGTH(ev_names); ++i) {
90 		/* skip EV_ prefix so @e is suffix of [EV_]XYZ */
91 		e = &ev_names[i].name[3];
92 		l = strlen(e);
93 
94 		/* compare prefix and test for trailing _ */
95 		if (len > l && startswith(name, len, e, l) && name[l] == '_')
96 			return ev_names[i].value;
97 	}
98 
99 	return -1;
100 }
101 
102 LIBEVDEV_EXPORT int
libevdev_event_code_from_name(unsigned int type,const char * name)103 libevdev_event_code_from_name(unsigned int type, const char *name)
104 {
105 	return libevdev_event_code_from_name_n(type, name, strlen(name));
106 }
107 
108 LIBEVDEV_EXPORT int
libevdev_event_code_from_name_n(unsigned int type,const char * name,size_t len)109 libevdev_event_code_from_name_n(unsigned int type, const char *name, size_t len)
110 {
111 	struct name_lookup lookup;
112 	const struct name_entry *entry;
113 	int real_type;
114 
115 	/* verify that @name is really of type @type */
116 	real_type = type_from_prefix(name, len);
117 	if (real_type < 0 || (unsigned int)real_type != type)
118 		return -1;
119 
120 	/* now look up the name @name and return the constant */
121 	lookup.name = name;
122 	lookup.len = len;
123 
124 	entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
125 
126 	return entry ? (int)entry->value : -1;
127 }
128 
129 LIBEVDEV_EXPORT int
libevdev_event_value_from_name(unsigned int type,unsigned int code,const char * name)130 libevdev_event_value_from_name(unsigned int type, unsigned int code, const char *name)
131 {
132 	return libevdev_event_value_from_name_n(type, code, name, strlen(name));
133 }
134 
135 LIBEVDEV_EXPORT int
libevdev_event_value_from_name_n(unsigned int type,unsigned int code,const char * name,size_t len)136 libevdev_event_value_from_name_n(unsigned int type, unsigned int code, const char *name, size_t len)
137 {
138 	struct name_lookup lookup;
139 	const struct name_entry *entry;
140 
141 	if (type != EV_ABS || code != ABS_MT_TOOL_TYPE)
142 		return -1;
143 
144 	lookup.name = name;
145 	lookup.len = len;
146 
147 	entry = lookup_name(tool_type_names, ARRAY_LENGTH(tool_type_names), &lookup);
148 
149 	return entry ? (int)entry->value : -1;
150 }
151 
152 LIBEVDEV_EXPORT int
libevdev_property_from_name(const char * name)153 libevdev_property_from_name(const char *name)
154 {
155 	return libevdev_property_from_name_n(name, strlen(name));
156 }
157 
158 LIBEVDEV_EXPORT int
libevdev_property_from_name_n(const char * name,size_t len)159 libevdev_property_from_name_n(const char *name, size_t len)
160 {
161 	struct name_lookup lookup;
162 	const struct name_entry *entry;
163 
164 	lookup.name = name;
165 	lookup.len = len;
166 
167 	entry = lookup_name(prop_names, ARRAY_LENGTH(prop_names), &lookup);
168 
169 	return entry ? (int)entry->value : -1;
170 }
171 
172 LIBEVDEV_EXPORT int
libevdev_event_code_from_code_name(const char * name)173 libevdev_event_code_from_code_name(const char *name)
174 {
175 	return libevdev_event_code_from_code_name_n(name, strlen(name));
176 }
177 
178 LIBEVDEV_EXPORT int
libevdev_event_code_from_code_name_n(const char * name,size_t len)179 libevdev_event_code_from_code_name_n(const char *name, size_t len)
180 {
181 	const struct name_entry *entry;
182 	struct name_lookup lookup;
183 
184 	/* now look up the name @name and return the constant */
185 	lookup.name = name;
186 	lookup.len = len;
187 
188 	entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
189 
190 	return entry ? (int)entry->value : -1;
191 }
192 
193 LIBEVDEV_EXPORT int
libevdev_event_type_from_code_name(const char * name)194 libevdev_event_type_from_code_name(const char *name)
195 {
196 	return libevdev_event_type_from_code_name_n(name, strlen(name));
197 }
198 
199 LIBEVDEV_EXPORT int
libevdev_event_type_from_code_name_n(const char * name,size_t len)200 libevdev_event_type_from_code_name_n(const char *name, size_t len)
201 {
202 	const struct name_entry *entry;
203 	struct name_lookup lookup;
204 
205 	/* First look up if the name exists, we dont' want to return a valid
206 	 * type for an invalid code name */
207 	lookup.name = name;
208 	lookup.len = len;
209 
210 	entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
211 
212 	return entry ? type_from_prefix(name, len) : -1;
213 }
214