1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::collections::BTreeMap;
6
7 use base::warn;
8 use linux_input_sys::constants::*;
9
10 use super::virtio_input_absinfo;
11 use super::virtio_input_bitmap;
12 use super::virtio_input_device_ids;
13 use super::VirtioInputConfig;
14
15 /// Instantiates a VirtioInputConfig object with the default configuration for a trackpad. It
16 /// supports touch, left button and right button events, as well as X and Y axis.
new_trackpad_config( idx: u32, width: u32, height: u32, name: Option<&str>, ) -> VirtioInputConfig17 pub fn new_trackpad_config(
18 idx: u32,
19 width: u32,
20 height: u32,
21 name: Option<&str>,
22 ) -> VirtioInputConfig {
23 let name = name
24 .map(str::to_owned)
25 .unwrap_or(format!("Crosvm Virtio Trackpad {idx}"));
26 VirtioInputConfig::new(
27 virtio_input_device_ids::new(0, 0, 0, 0),
28 name,
29 format!("virtio-trackpad-{idx}"),
30 virtio_input_bitmap::new([0u8; 128]),
31 default_trackpad_events(),
32 default_trackpad_absinfo(width, height),
33 )
34 }
35
new_multitouch_trackpad_config( idx: u32, width: u32, height: u32, name: Option<&str>, ) -> VirtioInputConfig36 pub fn new_multitouch_trackpad_config(
37 idx: u32,
38 width: u32,
39 height: u32,
40 name: Option<&str>,
41 ) -> VirtioInputConfig {
42 let name = name
43 .map(str::to_owned)
44 .unwrap_or(format!("Crosvm Virtio Multi-touch Trackpad {idx}"));
45 VirtioInputConfig::new(
46 virtio_input_device_ids::new(0, 0, 0, 0),
47 name,
48 format!("virtio-multi-touch-trackpad-{idx}"),
49 virtio_input_bitmap::from_bits(&[INPUT_PROP_POINTER, INPUT_PROP_BUTTONPAD]),
50 default_multitouchpad_events(),
51 default_multitouchpad_absinfo(width, height, 10, 65536),
52 )
53 }
54
55 /// Instantiates a VirtioInputConfig object with the default configuration for a mouse.
56 /// It supports left, right and middle buttons, as wel as X, Y and wheel relative axes.
new_mouse_config(idx: u32) -> VirtioInputConfig57 pub fn new_mouse_config(idx: u32) -> VirtioInputConfig {
58 VirtioInputConfig::new(
59 virtio_input_device_ids::new(0, 0, 0, 0),
60 format!("Crosvm Virtio Mouse {idx}"),
61 format!("virtio-mouse-{idx}"),
62 virtio_input_bitmap::new([0u8; 128]),
63 default_mouse_events(),
64 BTreeMap::new(),
65 )
66 }
67
68 /// Instantiates a VirtioInputConfig object with the default configuration for a keyboard.
69 /// It supports the same keys as a en-us keyboard and the CAPSLOCK, NUMLOCK and SCROLLLOCK leds.
new_keyboard_config(idx: u32) -> VirtioInputConfig70 pub fn new_keyboard_config(idx: u32) -> VirtioInputConfig {
71 VirtioInputConfig::new(
72 virtio_input_device_ids::new(0, 0, 0, 0),
73 format!("Crosvm Virtio Keyboard {idx}"),
74 format!("virtio-keyboard-{idx}"),
75 virtio_input_bitmap::new([0u8; 128]),
76 default_keyboard_events(),
77 BTreeMap::new(),
78 )
79 }
80
81 /// Instantiates a VirtioInputConfig object with the default configuration for a collection of
82 /// switches.
new_switches_config(idx: u32) -> VirtioInputConfig83 pub fn new_switches_config(idx: u32) -> VirtioInputConfig {
84 VirtioInputConfig::new(
85 virtio_input_device_ids::new(0, 0, 0, 0),
86 format!("Crosvm Virtio Switches {idx}"),
87 format!("virtio-switches-{idx}"),
88 virtio_input_bitmap::new([0u8; 128]),
89 default_switch_events(),
90 BTreeMap::new(),
91 )
92 }
93
94 /// Instantiates a VirtioInputConfig object with the default configuration for a collection of
95 /// rotary.
new_rotary_config(idx: u32) -> VirtioInputConfig96 pub fn new_rotary_config(idx: u32) -> VirtioInputConfig {
97 VirtioInputConfig::new(
98 virtio_input_device_ids::new(0, 0, 0, 0),
99 format!("Crosvm Virtio Rotary {idx}"),
100 format!("virtio-rotary-{idx}"),
101 virtio_input_bitmap::new([0u8; 128]),
102 default_rotary_events(),
103 BTreeMap::new(),
104 )
105 }
106
107 /// Instantiates a VirtioInputConfig object with the default configuration for a touchscreen (no
108 /// multitouch support).
new_single_touch_config( idx: u32, width: u32, height: u32, name: Option<&str>, ) -> VirtioInputConfig109 pub fn new_single_touch_config(
110 idx: u32,
111 width: u32,
112 height: u32,
113 name: Option<&str>,
114 ) -> VirtioInputConfig {
115 let name = name
116 .map(str::to_owned)
117 .unwrap_or(format!("Crosvm Virtio Touchscreen {idx}"));
118 VirtioInputConfig::new(
119 virtio_input_device_ids::new(0, 0, 0, 0),
120 name,
121 format!("virtio-touchscreen-{idx}"),
122 virtio_input_bitmap::from_bits(&[INPUT_PROP_DIRECT]),
123 default_touchscreen_events(),
124 default_touchscreen_absinfo(width, height),
125 )
126 }
127
128 /// Instantiates a VirtioInputConfig object with the default configuration for a multitouch
129 /// touchscreen.
new_multi_touch_config( idx: u32, width: u32, height: u32, name: Option<&str>, ) -> VirtioInputConfig130 pub fn new_multi_touch_config(
131 idx: u32,
132 width: u32,
133 height: u32,
134 name: Option<&str>,
135 ) -> VirtioInputConfig {
136 let name = name
137 .map(str::to_owned)
138 .unwrap_or(format!("Crosvm Virtio Multitouch Touchscreen {idx}"));
139 VirtioInputConfig::new(
140 virtio_input_device_ids::new(0, 0, 0, 0),
141 name,
142 format!("virtio-touchscreen-{idx}"),
143 virtio_input_bitmap::from_bits(&[INPUT_PROP_DIRECT]),
144 default_multitouchscreen_events(),
145 default_multitouchscreen_absinfo(width, height, 10, 10),
146 )
147 }
148
149 /// Initializes a VirtioInputConfig object for a custom virtio-input device.
150 ///
151 /// # Arguments
152 ///
153 /// * `idx` - input device index
154 /// * `name` - input device name
155 /// * `serial_name` - input device serial name
156 /// * `supported_events` - Event configuration provided by a configuration file
new_custom_config( idx: u32, name: &str, serial_name: &str, supported_events: BTreeMap<u16, virtio_input_bitmap>, ) -> VirtioInputConfig157 pub fn new_custom_config(
158 idx: u32,
159 name: &str,
160 serial_name: &str,
161 supported_events: BTreeMap<u16, virtio_input_bitmap>,
162 ) -> VirtioInputConfig {
163 let name: String = format!("{name} {idx}");
164 let serial_name = format!("{serial_name}-{idx}");
165 if name.as_bytes().len() > 128 {
166 warn!("name: {name} exceeds 128 bytes, will be truncated.");
167 }
168 if serial_name.as_bytes().len() > 128 {
169 warn!("serial_name: {serial_name} exceeds 128 bytes, will be truncated.");
170 }
171
172 VirtioInputConfig::new(
173 virtio_input_device_ids::new(0, 0, 0, 0),
174 name,
175 serial_name,
176 virtio_input_bitmap::new([0u8; 128]),
177 supported_events,
178 BTreeMap::new(),
179 )
180 }
181
default_touchscreen_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo>182 fn default_touchscreen_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo> {
183 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
184 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
185 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
186 absinfo
187 }
188
default_touchscreen_events() -> BTreeMap<u16, virtio_input_bitmap>189 fn default_touchscreen_events() -> BTreeMap<u16, virtio_input_bitmap> {
190 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
191 supported_events.insert(EV_KEY, virtio_input_bitmap::from_bits(&[BTN_TOUCH]));
192 supported_events.insert(EV_ABS, virtio_input_bitmap::from_bits(&[ABS_X, ABS_Y]));
193 supported_events
194 }
195
default_multitouchscreen_absinfo( width: u32, height: u32, slot: u32, id: u32, ) -> BTreeMap<u16, virtio_input_absinfo>196 fn default_multitouchscreen_absinfo(
197 width: u32,
198 height: u32,
199 slot: u32,
200 id: u32,
201 ) -> BTreeMap<u16, virtio_input_absinfo> {
202 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
203 absinfo.insert(ABS_MT_SLOT, virtio_input_absinfo::new(0, slot, 0, 0));
204 absinfo.insert(ABS_MT_TRACKING_ID, virtio_input_absinfo::new(0, id, 0, 0));
205 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
206 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
207 absinfo.insert(ABS_MT_POSITION_X, virtio_input_absinfo::new(0, width, 0, 0));
208 absinfo.insert(
209 ABS_MT_POSITION_Y,
210 virtio_input_absinfo::new(0, height, 0, 0),
211 );
212 absinfo
213 }
214
default_multitouchscreen_events() -> BTreeMap<u16, virtio_input_bitmap>215 fn default_multitouchscreen_events() -> BTreeMap<u16, virtio_input_bitmap> {
216 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
217 supported_events.insert(EV_KEY, virtio_input_bitmap::from_bits(&[BTN_TOUCH]));
218 supported_events.insert(
219 EV_ABS,
220 virtio_input_bitmap::from_bits(&[
221 ABS_MT_SLOT,
222 ABS_MT_TRACKING_ID,
223 ABS_MT_POSITION_X,
224 ABS_MT_POSITION_Y,
225 ABS_X,
226 ABS_Y,
227 ]),
228 );
229 supported_events
230 }
231
default_multitouchpad_absinfo( width: u32, height: u32, slot: u32, id: u32, ) -> BTreeMap<u16, virtio_input_absinfo>232 fn default_multitouchpad_absinfo(
233 width: u32,
234 height: u32,
235 slot: u32,
236 id: u32,
237 ) -> BTreeMap<u16, virtio_input_absinfo> {
238 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
239 absinfo.insert(ABS_MT_SLOT, virtio_input_absinfo::new(0, slot, 0, 0));
240 absinfo.insert(ABS_MT_TRACKING_ID, virtio_input_absinfo::new(0, id, 0, 0));
241 // TODO(b/347253952): make them configurable if necessary
242 absinfo.insert(ABS_MT_PRESSURE, virtio_input_absinfo::new(0, 255, 0, 0));
243 absinfo.insert(ABS_PRESSURE, virtio_input_absinfo::new(0, 255, 0, 0));
244 absinfo.insert(ABS_MT_TOUCH_MAJOR, virtio_input_absinfo::new(0, 4095, 0, 0));
245 absinfo.insert(ABS_MT_TOUCH_MINOR, virtio_input_absinfo::new(0, 4095, 0, 0));
246 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
247 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
248 absinfo.insert(ABS_MT_POSITION_X, virtio_input_absinfo::new(0, width, 0, 0));
249 absinfo.insert(ABS_MT_TOOL_TYPE, virtio_input_absinfo::new(0, 2, 0, 0));
250 absinfo.insert(
251 ABS_MT_POSITION_Y,
252 virtio_input_absinfo::new(0, height, 0, 0),
253 );
254 absinfo
255 }
256
default_multitouchpad_events() -> BTreeMap<u16, virtio_input_bitmap>257 fn default_multitouchpad_events() -> BTreeMap<u16, virtio_input_bitmap> {
258 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
259 supported_events.insert(
260 EV_KEY,
261 virtio_input_bitmap::from_bits(&[
262 BTN_TOUCH,
263 BTN_TOOL_FINGER,
264 BTN_TOOL_DOUBLETAP,
265 BTN_TOOL_TRIPLETAP,
266 BTN_TOOL_QUADTAP,
267 BTN_LEFT,
268 ]),
269 );
270 supported_events.insert(
271 EV_ABS,
272 virtio_input_bitmap::from_bits(&[
273 ABS_MT_SLOT,
274 ABS_MT_TRACKING_ID,
275 ABS_MT_POSITION_X,
276 ABS_MT_POSITION_Y,
277 ABS_MT_TOOL_TYPE,
278 ABS_MT_PRESSURE,
279 ABS_X,
280 ABS_Y,
281 ABS_PRESSURE,
282 ABS_MT_TOUCH_MAJOR,
283 ABS_MT_TOUCH_MINOR,
284 ABS_PRESSURE,
285 ]),
286 );
287 supported_events
288 }
289
default_trackpad_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo>290 fn default_trackpad_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo> {
291 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
292 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
293 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
294 absinfo
295 }
296
default_trackpad_events() -> BTreeMap<u16, virtio_input_bitmap>297 fn default_trackpad_events() -> BTreeMap<u16, virtio_input_bitmap> {
298 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
299 supported_events.insert(
300 EV_KEY,
301 virtio_input_bitmap::from_bits(&[BTN_TOOL_FINGER, BTN_TOUCH, BTN_LEFT, BTN_RIGHT]),
302 );
303 supported_events.insert(EV_ABS, virtio_input_bitmap::from_bits(&[ABS_X, ABS_Y]));
304 supported_events
305 }
306
default_mouse_events() -> BTreeMap<u16, virtio_input_bitmap>307 fn default_mouse_events() -> BTreeMap<u16, virtio_input_bitmap> {
308 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
309 supported_events.insert(
310 EV_KEY,
311 virtio_input_bitmap::from_bits(&[BTN_LEFT, BTN_RIGHT, BTN_MIDDLE]),
312 );
313 supported_events.insert(
314 EV_REL,
315 virtio_input_bitmap::from_bits(&[REL_X, REL_Y, REL_WHEEL]),
316 );
317 supported_events
318 }
319
default_keyboard_events() -> BTreeMap<u16, virtio_input_bitmap>320 fn default_keyboard_events() -> BTreeMap<u16, virtio_input_bitmap> {
321 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
322 supported_events.insert(
323 EV_KEY,
324 virtio_input_bitmap::from_bits(&[
325 KEY_ESC,
326 KEY_1,
327 KEY_2,
328 KEY_3,
329 KEY_4,
330 KEY_5,
331 KEY_6,
332 KEY_7,
333 KEY_8,
334 KEY_9,
335 KEY_0,
336 KEY_MINUS,
337 KEY_EQUAL,
338 KEY_BACKSPACE,
339 KEY_TAB,
340 KEY_Q,
341 KEY_W,
342 KEY_E,
343 KEY_R,
344 KEY_T,
345 KEY_Y,
346 KEY_U,
347 KEY_I,
348 KEY_O,
349 KEY_P,
350 KEY_LEFTBRACE,
351 KEY_RIGHTBRACE,
352 KEY_ENTER,
353 KEY_LEFTCTRL,
354 KEY_A,
355 KEY_S,
356 KEY_D,
357 KEY_F,
358 KEY_G,
359 KEY_H,
360 KEY_J,
361 KEY_K,
362 KEY_L,
363 KEY_SEMICOLON,
364 KEY_APOSTROPHE,
365 KEY_GRAVE,
366 KEY_LEFTSHIFT,
367 KEY_BACKSLASH,
368 KEY_Z,
369 KEY_X,
370 KEY_C,
371 KEY_V,
372 KEY_B,
373 KEY_N,
374 KEY_M,
375 KEY_COMMA,
376 KEY_DOT,
377 KEY_SLASH,
378 KEY_RIGHTSHIFT,
379 KEY_KPASTERISK,
380 KEY_LEFTALT,
381 KEY_SPACE,
382 KEY_CAPSLOCK,
383 KEY_F1,
384 KEY_F2,
385 KEY_F3,
386 KEY_F4,
387 KEY_F5,
388 KEY_F6,
389 KEY_F7,
390 KEY_F8,
391 KEY_F9,
392 KEY_F10,
393 KEY_NUMLOCK,
394 KEY_SCROLLLOCK,
395 KEY_KP7,
396 KEY_KP8,
397 KEY_KP9,
398 KEY_KPMINUS,
399 KEY_KP4,
400 KEY_KP5,
401 KEY_KP6,
402 KEY_KPPLUS,
403 KEY_KP1,
404 KEY_KP2,
405 KEY_KP3,
406 KEY_KP0,
407 KEY_KPDOT,
408 KEY_F11,
409 KEY_F12,
410 KEY_KPENTER,
411 KEY_RIGHTCTRL,
412 KEY_KPSLASH,
413 KEY_SYSRQ,
414 KEY_RIGHTALT,
415 KEY_HOME,
416 KEY_UP,
417 KEY_PAGEUP,
418 KEY_LEFT,
419 KEY_RIGHT,
420 KEY_END,
421 KEY_DOWN,
422 KEY_PAGEDOWN,
423 KEY_INSERT,
424 KEY_DELETE,
425 KEY_PAUSE,
426 KEY_MENU,
427 KEY_PRINT,
428 KEY_POWER,
429 KEY_HOMEPAGE,
430 KEY_MUTE,
431 KEY_VOLUMEDOWN,
432 KEY_VOLUMEUP,
433 KEY_BACK,
434 ]),
435 );
436 supported_events.insert(
437 EV_REP,
438 virtio_input_bitmap::from_bits(&[REP_DELAY, REP_PERIOD]),
439 );
440 supported_events.insert(
441 EV_LED,
442 virtio_input_bitmap::from_bits(&[LED_CAPSL, LED_NUML, LED_SCROLLL]),
443 );
444 supported_events
445 }
446
default_switch_events() -> BTreeMap<u16, virtio_input_bitmap>447 fn default_switch_events() -> BTreeMap<u16, virtio_input_bitmap> {
448 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
449 supported_events.insert(
450 EV_SW,
451 virtio_input_bitmap::from_bits(&[
452 SW_LID,
453 SW_TABLET_MODE,
454 SW_HEADPHONE_INSERT,
455 SW_RFKILL_ALL,
456 SW_MICROPHONE_INSERT,
457 SW_DOCK,
458 SW_LINEOUT_INSERT,
459 SW_JACK_PHYSICAL_INSERT,
460 SW_VIDEOOUT_INSERT,
461 SW_CAMERA_LENS_COVER,
462 SW_KEYPAD_SLIDE,
463 SW_FRONT_PROXIMITY,
464 SW_ROTATE_LOCK,
465 SW_LINEIN_INSERT,
466 SW_MUTE_DEVICE,
467 SW_PEN_INSERTED,
468 SW_MACHINE_COVER,
469 ]),
470 );
471 supported_events
472 }
473
default_rotary_events() -> BTreeMap<u16, virtio_input_bitmap>474 fn default_rotary_events() -> BTreeMap<u16, virtio_input_bitmap> {
475 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
476 supported_events.insert(EV_REL, virtio_input_bitmap::from_bits(&[REL_WHEEL]));
477 supported_events
478 }
479
480 #[cfg(test)]
481 mod tests {
482 use super::*;
483
484 #[test]
test_new_switches_config()485 fn test_new_switches_config() {
486 let config = new_switches_config(0);
487 assert_eq!(config.serial_name, "virtio-switches-0");
488
489 let events = config.supported_events;
490 assert_eq!(events.len(), 1);
491 assert_eq!(events.contains_key(&EV_SW), true);
492
493 // The bitmap should contain SW_CNT=0x10+1=17 ones,
494 // where each one is packed into the u8 bitmap.
495 let mut expected_bitmap = [0_u8; 128];
496 expected_bitmap[0] = 0b11111111u8;
497 expected_bitmap[1] = 0b11111111u8;
498 expected_bitmap[2] = 0b1u8;
499 assert_eq!(events[&EV_SW].bitmap, expected_bitmap);
500 }
501 }
502