FreeBSD/Linux Kernel Cross Reference
sys/dev/hid/hcons.c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32 * Consumer Controls usage page driver
33 * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
34 */
35
36 #include <sys/param.h>
37 #include <sys/bitstring.h>
38 #include <sys/bus.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/sysctl.h>
42
43 #include <dev/evdev/input.h>
44 #include <dev/evdev/evdev.h>
45
46 #include <dev/hid/hid.h>
47 #include <dev/hid/hidbus.h>
48 #include <dev/hid/hidmap.h>
49
50 static hidmap_cb_t hcons_rel_volume_cb;
51
52 #define HCONS_MAP_KEY(usage, code) \
53 { HIDMAP_KEY(HUP_CONSUMER, usage, code) }
54 #define HCONS_MAP_ABS(usage, code) \
55 { HIDMAP_ABS(HUP_CONSUMER, usage, code) }
56 #define HCONS_MAP_REL(usage, code) \
57 { HIDMAP_REL(HUP_CONSUMER, usage, code) }
58 #define HCONS_MAP_REL_CB(usage, callback) \
59 { HIDMAP_REL_CB(HUP_CONSUMER, usage, &callback) }
60
61 static const struct hidmap_item hcons_map[] = {
62 HCONS_MAP_KEY(0x030, KEY_POWER),
63 HCONS_MAP_KEY(0x031, KEY_RESTART),
64 HCONS_MAP_KEY(0x032, KEY_SLEEP),
65 HCONS_MAP_KEY(0x034, KEY_SLEEP),
66 HCONS_MAP_KEY(0x035, KEY_KBDILLUMTOGGLE),
67 HCONS_MAP_KEY(0x036, BTN_MISC),
68 HCONS_MAP_KEY(0x040, KEY_MENU), /* Menu */
69 HCONS_MAP_KEY(0x041, KEY_SELECT), /* Menu Pick */
70 HCONS_MAP_KEY(0x042, KEY_UP), /* Menu Up */
71 HCONS_MAP_KEY(0x043, KEY_DOWN), /* Menu Down */
72 HCONS_MAP_KEY(0x044, KEY_LEFT), /* Menu Left */
73 HCONS_MAP_KEY(0x045, KEY_RIGHT), /* Menu Right */
74 HCONS_MAP_KEY(0x046, KEY_ESC), /* Menu Escape */
75 HCONS_MAP_KEY(0x047, KEY_KPPLUS), /* Menu Value Increase */
76 HCONS_MAP_KEY(0x048, KEY_KPMINUS), /* Menu Value Decrease */
77 HCONS_MAP_KEY(0x060, KEY_INFO), /* Data On Screen */
78 HCONS_MAP_KEY(0x061, KEY_SUBTITLE), /* Closed Caption */
79 HCONS_MAP_KEY(0x063, KEY_VCR), /* VCR/TV */
80 HCONS_MAP_KEY(0x065, KEY_CAMERA), /* Snapshot */
81 HCONS_MAP_KEY(0x069, KEY_RED),
82 HCONS_MAP_KEY(0x06a, KEY_GREEN),
83 HCONS_MAP_KEY(0x06b, KEY_BLUE),
84 HCONS_MAP_KEY(0x06c, KEY_YELLOW),
85 HCONS_MAP_KEY(0x06d, KEY_ASPECT_RATIO),
86 HCONS_MAP_KEY(0x06f, KEY_BRIGHTNESSUP),
87 HCONS_MAP_KEY(0x070, KEY_BRIGHTNESSDOWN),
88 HCONS_MAP_KEY(0x072, KEY_BRIGHTNESS_TOGGLE),
89 HCONS_MAP_KEY(0x073, KEY_BRIGHTNESS_MIN),
90 HCONS_MAP_KEY(0x074, KEY_BRIGHTNESS_MAX),
91 HCONS_MAP_KEY(0x075, KEY_BRIGHTNESS_AUTO),
92 HCONS_MAP_KEY(0x079, KEY_KBDILLUMUP),
93 HCONS_MAP_KEY(0x07a, KEY_KBDILLUMDOWN),
94 HCONS_MAP_KEY(0x07c, KEY_KBDILLUMTOGGLE),
95 HCONS_MAP_KEY(0x082, KEY_VIDEO_NEXT),
96 HCONS_MAP_KEY(0x083, KEY_LAST),
97 HCONS_MAP_KEY(0x084, KEY_ENTER),
98 HCONS_MAP_KEY(0x088, KEY_PC),
99 HCONS_MAP_KEY(0x089, KEY_TV),
100 HCONS_MAP_KEY(0x08a, KEY_WWW),
101 HCONS_MAP_KEY(0x08b, KEY_DVD),
102 HCONS_MAP_KEY(0x08c, KEY_PHONE),
103 HCONS_MAP_KEY(0x08d, KEY_PROGRAM),
104 HCONS_MAP_KEY(0x08e, KEY_VIDEOPHONE),
105 HCONS_MAP_KEY(0x08f, KEY_GAMES),
106 HCONS_MAP_KEY(0x090, KEY_MEMO),
107 HCONS_MAP_KEY(0x091, KEY_CD),
108 HCONS_MAP_KEY(0x092, KEY_VCR),
109 HCONS_MAP_KEY(0x093, KEY_TUNER),
110 HCONS_MAP_KEY(0x094, KEY_EXIT),
111 HCONS_MAP_KEY(0x095, KEY_HELP),
112 HCONS_MAP_KEY(0x096, KEY_TAPE),
113 HCONS_MAP_KEY(0x097, KEY_TV2),
114 HCONS_MAP_KEY(0x098, KEY_SAT),
115 HCONS_MAP_KEY(0x09a, KEY_PVR),
116 HCONS_MAP_KEY(0x09c, KEY_CHANNELUP),
117 HCONS_MAP_KEY(0x09d, KEY_CHANNELDOWN),
118 HCONS_MAP_KEY(0x0a0, KEY_VCR2),
119 HCONS_MAP_KEY(0x0b0, KEY_PLAY),
120 HCONS_MAP_KEY(0x0b1, KEY_PAUSE),
121 HCONS_MAP_KEY(0x0b2, KEY_RECORD),
122 HCONS_MAP_KEY(0x0b3, KEY_FASTFORWARD),
123 HCONS_MAP_KEY(0x0b4, KEY_REWIND),
124 HCONS_MAP_KEY(0x0b5, KEY_NEXTSONG),
125 HCONS_MAP_KEY(0x0b6, KEY_PREVIOUSSONG),
126 HCONS_MAP_KEY(0x0b7, KEY_STOPCD),
127 HCONS_MAP_KEY(0x0b8, KEY_EJECTCD),
128 HCONS_MAP_KEY(0x0bc, KEY_MEDIA_REPEAT),
129 HCONS_MAP_KEY(0x0b9, KEY_SHUFFLE),
130 HCONS_MAP_KEY(0x0bf, KEY_SLOW),
131 HCONS_MAP_KEY(0x0cd, KEY_PLAYPAUSE),
132 HCONS_MAP_KEY(0x0cf, KEY_VOICECOMMAND),
133 HCONS_MAP_ABS(0x0e0, ABS_VOLUME),
134 HCONS_MAP_REL_CB(0x0e0, hcons_rel_volume_cb),
135 HCONS_MAP_KEY(0x0e2, KEY_MUTE),
136 HCONS_MAP_KEY(0x0e5, KEY_BASSBOOST),
137 HCONS_MAP_KEY(0x0e9, KEY_VOLUMEUP),
138 HCONS_MAP_KEY(0x0ea, KEY_VOLUMEDOWN),
139 HCONS_MAP_KEY(0x0f5, KEY_SLOW),
140 HCONS_MAP_KEY(0x181, KEY_BUTTONCONFIG),
141 HCONS_MAP_KEY(0x182, KEY_BOOKMARKS),
142 HCONS_MAP_KEY(0x183, KEY_CONFIG),
143 HCONS_MAP_KEY(0x184, KEY_WORDPROCESSOR),
144 HCONS_MAP_KEY(0x185, KEY_EDITOR),
145 HCONS_MAP_KEY(0x186, KEY_SPREADSHEET),
146 HCONS_MAP_KEY(0x187, KEY_GRAPHICSEDITOR),
147 HCONS_MAP_KEY(0x188, KEY_PRESENTATION),
148 HCONS_MAP_KEY(0x189, KEY_DATABASE),
149 HCONS_MAP_KEY(0x18a, KEY_MAIL),
150 HCONS_MAP_KEY(0x18b, KEY_NEWS),
151 HCONS_MAP_KEY(0x18c, KEY_VOICEMAIL),
152 HCONS_MAP_KEY(0x18d, KEY_ADDRESSBOOK),
153 HCONS_MAP_KEY(0x18e, KEY_CALENDAR),
154 HCONS_MAP_KEY(0x18f, KEY_TASKMANAGER),
155 HCONS_MAP_KEY(0x190, KEY_JOURNAL),
156 HCONS_MAP_KEY(0x191, KEY_FINANCE),
157 HCONS_MAP_KEY(0x192, KEY_CALC),
158 HCONS_MAP_KEY(0x193, KEY_PLAYER),
159 HCONS_MAP_KEY(0x194, KEY_FILE),
160 HCONS_MAP_KEY(0x196, KEY_WWW),
161 HCONS_MAP_KEY(0x199, KEY_CHAT),
162 HCONS_MAP_KEY(0x19c, KEY_LOGOFF),
163 HCONS_MAP_KEY(0x19e, KEY_COFFEE),
164 HCONS_MAP_KEY(0x19f, KEY_CONTROLPANEL),
165 HCONS_MAP_KEY(0x1a2, KEY_APPSELECT),
166 HCONS_MAP_KEY(0x1a3, KEY_NEXT),
167 HCONS_MAP_KEY(0x1a4, KEY_PREVIOUS),
168 HCONS_MAP_KEY(0x1a6, KEY_HELP),
169 HCONS_MAP_KEY(0x1a7, KEY_DOCUMENTS),
170 HCONS_MAP_KEY(0x1ab, KEY_SPELLCHECK),
171 HCONS_MAP_KEY(0x1ae, KEY_KEYBOARD),
172 HCONS_MAP_KEY(0x1b1, KEY_SCREENSAVER),
173 HCONS_MAP_KEY(0x1b4, KEY_FILE),
174 HCONS_MAP_KEY(0x1b6, KEY_IMAGES),
175 HCONS_MAP_KEY(0x1b7, KEY_AUDIO),
176 HCONS_MAP_KEY(0x1b8, KEY_VIDEO),
177 HCONS_MAP_KEY(0x1bc, KEY_MESSENGER),
178 HCONS_MAP_KEY(0x1bd, KEY_INFO),
179 HCONS_MAP_KEY(0x1cb, KEY_ASSISTANT),
180 HCONS_MAP_KEY(0x201, KEY_NEW),
181 HCONS_MAP_KEY(0x202, KEY_OPEN),
182 HCONS_MAP_KEY(0x203, KEY_CLOSE),
183 HCONS_MAP_KEY(0x204, KEY_EXIT),
184 HCONS_MAP_KEY(0x207, KEY_SAVE),
185 HCONS_MAP_KEY(0x208, KEY_PRINT),
186 HCONS_MAP_KEY(0x209, KEY_PROPS),
187 HCONS_MAP_KEY(0x21a, KEY_UNDO),
188 HCONS_MAP_KEY(0x21b, KEY_COPY),
189 HCONS_MAP_KEY(0x21c, KEY_CUT),
190 HCONS_MAP_KEY(0x21d, KEY_PASTE),
191 HCONS_MAP_KEY(0x21f, KEY_FIND),
192 HCONS_MAP_KEY(0x221, KEY_SEARCH),
193 HCONS_MAP_KEY(0x222, KEY_GOTO),
194 HCONS_MAP_KEY(0x223, KEY_HOMEPAGE),
195 HCONS_MAP_KEY(0x224, KEY_BACK),
196 HCONS_MAP_KEY(0x225, KEY_FORWARD),
197 HCONS_MAP_KEY(0x226, KEY_STOP),
198 HCONS_MAP_KEY(0x227, KEY_REFRESH),
199 HCONS_MAP_KEY(0x22a, KEY_BOOKMARKS),
200 HCONS_MAP_KEY(0x22d, KEY_ZOOMIN),
201 HCONS_MAP_KEY(0x22e, KEY_ZOOMOUT),
202 HCONS_MAP_KEY(0x22f, KEY_ZOOMRESET),
203 HCONS_MAP_KEY(0x232, KEY_FULL_SCREEN),
204 HCONS_MAP_KEY(0x233, KEY_SCROLLUP),
205 HCONS_MAP_KEY(0x234, KEY_SCROLLDOWN),
206 HCONS_MAP_REL(0x238, REL_HWHEEL), /* AC Pan */
207 HCONS_MAP_KEY(0x23d, KEY_EDIT),
208 HCONS_MAP_KEY(0x25f, KEY_CANCEL),
209 HCONS_MAP_KEY(0x269, KEY_INSERT),
210 HCONS_MAP_KEY(0x26a, KEY_DELETE),
211 HCONS_MAP_KEY(0x279, KEY_REDO),
212 HCONS_MAP_KEY(0x289, KEY_REPLY),
213 HCONS_MAP_KEY(0x28b, KEY_FORWARDMAIL),
214 HCONS_MAP_KEY(0x28c, KEY_SEND),
215 HCONS_MAP_KEY(0x29d, KEY_KBD_LAYOUT_NEXT),
216 HCONS_MAP_KEY(0x2c7, KEY_KBDINPUTASSIST_PREV),
217 HCONS_MAP_KEY(0x2c8, KEY_KBDINPUTASSIST_NEXT),
218 HCONS_MAP_KEY(0x2c9, KEY_KBDINPUTASSIST_PREVGROUP),
219 HCONS_MAP_KEY(0x2ca, KEY_KBDINPUTASSIST_NEXTGROUP),
220 HCONS_MAP_KEY(0x2cb, KEY_KBDINPUTASSIST_ACCEPT),
221 HCONS_MAP_KEY(0x2cc, KEY_KBDINPUTASSIST_CANCEL),
222 HCONS_MAP_KEY(0x29f, KEY_SCALE),
223 };
224
225 static const struct hid_device_id hcons_devs[] = {
226 { HID_TLC(HUP_CONSUMER, HUC_CONTROL) },
227 };
228
229 /*
230 * Emulate relative Consumer volume usage with pressing
231 * VOLUMEUP and VOLUMEDOWN keys appropriate number of times
232 */
233 static int
234 hcons_rel_volume_cb(HIDMAP_CB_ARGS)
235 {
236 struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
237 int32_t code;
238 int nrepeats;
239
240 switch (HIDMAP_CB_GET_STATE()) {
241 case HIDMAP_CB_IS_ATTACHING:
242 evdev_support_event(evdev, EV_KEY);
243 evdev_support_key(evdev, KEY_VOLUMEUP);
244 evdev_support_key(evdev, KEY_VOLUMEDOWN);
245 break;
246 case HIDMAP_CB_IS_RUNNING:
247 /* Nothing to report. */
248 if (ctx.data == 0)
249 return (ENOMSG);
250 code = ctx.data > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
251 for (nrepeats = abs(ctx.data); nrepeats > 0; nrepeats--) {
252 evdev_push_key(evdev, code, 1);
253 evdev_push_key(evdev, code, 0);
254 }
255 break;
256 default:
257 break;
258 }
259
260 return (0);
261 }
262
263 static int
264 hcons_probe(device_t dev)
265 {
266 return (HIDMAP_PROBE(device_get_softc(dev), dev,
267 hcons_devs, hcons_map, "Consumer Control"));
268 }
269
270 static int
271 hcons_attach(device_t dev)
272 {
273 return (hidmap_attach(device_get_softc(dev)));
274 }
275
276 static int
277 hcons_detach(device_t dev)
278 {
279 return (hidmap_detach(device_get_softc(dev)));
280 }
281
282 static devclass_t hcons_devclass;
283 static device_method_t hcons_methods[] = {
284 DEVMETHOD(device_probe, hcons_probe),
285 DEVMETHOD(device_attach, hcons_attach),
286 DEVMETHOD(device_detach, hcons_detach),
287
288 DEVMETHOD_END
289 };
290
291 DEFINE_CLASS_0(hcons, hcons_driver, hcons_methods, sizeof(struct hidmap));
292 DRIVER_MODULE(hcons, hidbus, hcons_driver, hcons_devclass, NULL, 0);
293 MODULE_DEPEND(hcons, hid, 1, 1, 1);
294 MODULE_DEPEND(hcons, hidbus, 1, 1, 1);
295 MODULE_DEPEND(hcons, hidmap, 1, 1, 1);
296 MODULE_DEPEND(hcons, evdev, 1, 1, 1);
297 MODULE_VERSION(hcons, 1);
298 HID_PNP_INFO(hcons_devs);
Cache object: 3e2272593972cf0d64b2861279ba2dbb
|