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 /// * `properties` - input device properties
157 /// * `supported_events` - Event configuration provided by a configuration file
158 /// * `axis_info` - Device axis configuration
new_custom_config( idx: u32, name: &str, serial_name: &str, properties: virtio_input_bitmap, supported_events: BTreeMap<u16, virtio_input_bitmap>, axis_info: BTreeMap<u16, virtio_input_absinfo>, ) -> VirtioInputConfig159 pub fn new_custom_config(
160 idx: u32,
161 name: &str,
162 serial_name: &str,
163 properties: virtio_input_bitmap,
164 supported_events: BTreeMap<u16, virtio_input_bitmap>,
165 axis_info: BTreeMap<u16, virtio_input_absinfo>,
166 ) -> VirtioInputConfig {
167 let name: String = format!("{name} {idx}");
168 let serial_name = format!("{serial_name}-{idx}");
169 if name.len() > 128 {
170 warn!("name: {name} exceeds 128 bytes, will be truncated.");
171 }
172 if serial_name.len() > 128 {
173 warn!("serial_name: {serial_name} exceeds 128 bytes, will be truncated.");
174 }
175
176 VirtioInputConfig::new(
177 virtio_input_device_ids::new(0, 0, 0, 0),
178 name,
179 serial_name,
180 properties,
181 supported_events,
182 axis_info,
183 )
184 }
185
default_touchscreen_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo>186 fn default_touchscreen_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo> {
187 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
188 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
189 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
190 absinfo
191 }
192
default_touchscreen_events() -> BTreeMap<u16, virtio_input_bitmap>193 fn default_touchscreen_events() -> BTreeMap<u16, virtio_input_bitmap> {
194 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
195 supported_events.insert(EV_KEY, virtio_input_bitmap::from_bits(&[BTN_TOUCH]));
196 supported_events.insert(EV_ABS, virtio_input_bitmap::from_bits(&[ABS_X, ABS_Y]));
197 supported_events
198 }
199
default_multitouchscreen_absinfo( width: u32, height: u32, slot: u32, id: u32, ) -> BTreeMap<u16, virtio_input_absinfo>200 fn default_multitouchscreen_absinfo(
201 width: u32,
202 height: u32,
203 slot: u32,
204 id: u32,
205 ) -> BTreeMap<u16, virtio_input_absinfo> {
206 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
207 absinfo.insert(ABS_MT_SLOT, virtio_input_absinfo::new(0, slot, 0, 0));
208 absinfo.insert(ABS_MT_TRACKING_ID, virtio_input_absinfo::new(0, id, 0, 0));
209 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
210 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
211 absinfo.insert(ABS_MT_POSITION_X, virtio_input_absinfo::new(0, width, 0, 0));
212 absinfo.insert(
213 ABS_MT_POSITION_Y,
214 virtio_input_absinfo::new(0, height, 0, 0),
215 );
216 absinfo
217 }
218
default_multitouchscreen_events() -> BTreeMap<u16, virtio_input_bitmap>219 fn default_multitouchscreen_events() -> BTreeMap<u16, virtio_input_bitmap> {
220 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
221 supported_events.insert(EV_KEY, virtio_input_bitmap::from_bits(&[BTN_TOUCH]));
222 supported_events.insert(
223 EV_ABS,
224 virtio_input_bitmap::from_bits(&[
225 ABS_MT_SLOT,
226 ABS_MT_TRACKING_ID,
227 ABS_MT_POSITION_X,
228 ABS_MT_POSITION_Y,
229 ABS_X,
230 ABS_Y,
231 ]),
232 );
233 supported_events
234 }
235
default_multitouchpad_absinfo( width: u32, height: u32, slot: u32, id: u32, ) -> BTreeMap<u16, virtio_input_absinfo>236 fn default_multitouchpad_absinfo(
237 width: u32,
238 height: u32,
239 slot: u32,
240 id: u32,
241 ) -> BTreeMap<u16, virtio_input_absinfo> {
242 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
243 absinfo.insert(ABS_MT_SLOT, virtio_input_absinfo::new(0, slot, 0, 0));
244 absinfo.insert(ABS_MT_TRACKING_ID, virtio_input_absinfo::new(0, id, 0, 0));
245 // TODO(b/347253952): make them configurable if necessary
246 absinfo.insert(ABS_MT_PRESSURE, virtio_input_absinfo::new(0, 255, 0, 0));
247 absinfo.insert(ABS_PRESSURE, virtio_input_absinfo::new(0, 255, 0, 0));
248 absinfo.insert(ABS_MT_TOUCH_MAJOR, virtio_input_absinfo::new(0, 4095, 0, 0));
249 absinfo.insert(ABS_MT_TOUCH_MINOR, virtio_input_absinfo::new(0, 4095, 0, 0));
250 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
251 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
252 absinfo.insert(ABS_MT_POSITION_X, virtio_input_absinfo::new(0, width, 0, 0));
253 absinfo.insert(ABS_MT_TOOL_TYPE, virtio_input_absinfo::new(0, 2, 0, 0));
254 absinfo.insert(
255 ABS_MT_POSITION_Y,
256 virtio_input_absinfo::new(0, height, 0, 0),
257 );
258 absinfo
259 }
260
default_multitouchpad_events() -> BTreeMap<u16, virtio_input_bitmap>261 fn default_multitouchpad_events() -> BTreeMap<u16, virtio_input_bitmap> {
262 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
263 supported_events.insert(
264 EV_KEY,
265 virtio_input_bitmap::from_bits(&[
266 BTN_TOUCH,
267 BTN_TOOL_FINGER,
268 BTN_TOOL_DOUBLETAP,
269 BTN_TOOL_TRIPLETAP,
270 BTN_TOOL_QUADTAP,
271 BTN_LEFT,
272 ]),
273 );
274 supported_events.insert(
275 EV_ABS,
276 virtio_input_bitmap::from_bits(&[
277 ABS_MT_SLOT,
278 ABS_MT_TRACKING_ID,
279 ABS_MT_POSITION_X,
280 ABS_MT_POSITION_Y,
281 ABS_MT_TOOL_TYPE,
282 ABS_MT_PRESSURE,
283 ABS_X,
284 ABS_Y,
285 ABS_PRESSURE,
286 ABS_MT_TOUCH_MAJOR,
287 ABS_MT_TOUCH_MINOR,
288 ABS_PRESSURE,
289 ]),
290 );
291 supported_events
292 }
293
default_trackpad_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo>294 fn default_trackpad_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo> {
295 let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
296 absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
297 absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
298 absinfo
299 }
300
default_trackpad_events() -> BTreeMap<u16, virtio_input_bitmap>301 fn default_trackpad_events() -> BTreeMap<u16, virtio_input_bitmap> {
302 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
303 supported_events.insert(
304 EV_KEY,
305 virtio_input_bitmap::from_bits(&[BTN_TOOL_FINGER, BTN_TOUCH, BTN_LEFT, BTN_RIGHT]),
306 );
307 supported_events.insert(EV_ABS, virtio_input_bitmap::from_bits(&[ABS_X, ABS_Y]));
308 supported_events
309 }
310
default_mouse_events() -> BTreeMap<u16, virtio_input_bitmap>311 fn default_mouse_events() -> BTreeMap<u16, virtio_input_bitmap> {
312 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
313 supported_events.insert(
314 EV_KEY,
315 virtio_input_bitmap::from_bits(&[BTN_LEFT, BTN_RIGHT, BTN_MIDDLE]),
316 );
317 supported_events.insert(
318 EV_REL,
319 virtio_input_bitmap::from_bits(&[REL_X, REL_Y, REL_WHEEL]),
320 );
321 supported_events
322 }
323
default_keyboard_events() -> BTreeMap<u16, virtio_input_bitmap>324 fn default_keyboard_events() -> BTreeMap<u16, virtio_input_bitmap> {
325 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
326 supported_events.insert(
327 EV_KEY,
328 virtio_input_bitmap::from_bits(&[
329 KEY_ESC,
330 KEY_1,
331 KEY_2,
332 KEY_3,
333 KEY_4,
334 KEY_5,
335 KEY_6,
336 KEY_7,
337 KEY_8,
338 KEY_9,
339 KEY_0,
340 KEY_MINUS,
341 KEY_EQUAL,
342 KEY_BACKSPACE,
343 KEY_TAB,
344 KEY_Q,
345 KEY_W,
346 KEY_E,
347 KEY_R,
348 KEY_T,
349 KEY_Y,
350 KEY_U,
351 KEY_I,
352 KEY_O,
353 KEY_P,
354 KEY_LEFTBRACE,
355 KEY_RIGHTBRACE,
356 KEY_ENTER,
357 KEY_LEFTCTRL,
358 KEY_A,
359 KEY_S,
360 KEY_D,
361 KEY_F,
362 KEY_G,
363 KEY_H,
364 KEY_J,
365 KEY_K,
366 KEY_L,
367 KEY_SEMICOLON,
368 KEY_APOSTROPHE,
369 KEY_GRAVE,
370 KEY_LEFTSHIFT,
371 KEY_BACKSLASH,
372 KEY_Z,
373 KEY_X,
374 KEY_C,
375 KEY_V,
376 KEY_B,
377 KEY_N,
378 KEY_M,
379 KEY_COMMA,
380 KEY_DOT,
381 KEY_SLASH,
382 KEY_RIGHTSHIFT,
383 KEY_KPASTERISK,
384 KEY_LEFTALT,
385 KEY_SPACE,
386 KEY_CAPSLOCK,
387 KEY_F1,
388 KEY_F2,
389 KEY_F3,
390 KEY_F4,
391 KEY_F5,
392 KEY_F6,
393 KEY_F7,
394 KEY_F8,
395 KEY_F9,
396 KEY_F10,
397 KEY_NUMLOCK,
398 KEY_SCROLLLOCK,
399 KEY_KP7,
400 KEY_KP8,
401 KEY_KP9,
402 KEY_KPMINUS,
403 KEY_KP4,
404 KEY_KP5,
405 KEY_KP6,
406 KEY_KPPLUS,
407 KEY_KP1,
408 KEY_KP2,
409 KEY_KP3,
410 KEY_KP0,
411 KEY_KPDOT,
412 KEY_F11,
413 KEY_F12,
414 KEY_KPENTER,
415 KEY_RIGHTCTRL,
416 KEY_KPSLASH,
417 KEY_SYSRQ,
418 KEY_RIGHTALT,
419 KEY_HOME,
420 KEY_UP,
421 KEY_PAGEUP,
422 KEY_LEFT,
423 KEY_RIGHT,
424 KEY_END,
425 KEY_DOWN,
426 KEY_PAGEDOWN,
427 KEY_INSERT,
428 KEY_DELETE,
429 KEY_PAUSE,
430 KEY_MENU,
431 KEY_PRINT,
432 KEY_POWER,
433 KEY_HOMEPAGE,
434 KEY_MUTE,
435 KEY_VOLUMEDOWN,
436 KEY_VOLUMEUP,
437 KEY_BACK,
438 ]),
439 );
440 supported_events.insert(
441 EV_REP,
442 virtio_input_bitmap::from_bits(&[REP_DELAY, REP_PERIOD]),
443 );
444 supported_events.insert(
445 EV_LED,
446 virtio_input_bitmap::from_bits(&[LED_CAPSL, LED_NUML, LED_SCROLLL]),
447 );
448 supported_events
449 }
450
default_switch_events() -> BTreeMap<u16, virtio_input_bitmap>451 fn default_switch_events() -> BTreeMap<u16, virtio_input_bitmap> {
452 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
453 supported_events.insert(
454 EV_SW,
455 virtio_input_bitmap::from_bits(&[
456 SW_LID,
457 SW_TABLET_MODE,
458 SW_HEADPHONE_INSERT,
459 SW_RFKILL_ALL,
460 SW_MICROPHONE_INSERT,
461 SW_DOCK,
462 SW_LINEOUT_INSERT,
463 SW_JACK_PHYSICAL_INSERT,
464 SW_VIDEOOUT_INSERT,
465 SW_CAMERA_LENS_COVER,
466 SW_KEYPAD_SLIDE,
467 SW_FRONT_PROXIMITY,
468 SW_ROTATE_LOCK,
469 SW_LINEIN_INSERT,
470 SW_MUTE_DEVICE,
471 SW_PEN_INSERTED,
472 SW_MACHINE_COVER,
473 ]),
474 );
475 supported_events
476 }
477
default_rotary_events() -> BTreeMap<u16, virtio_input_bitmap>478 fn default_rotary_events() -> BTreeMap<u16, virtio_input_bitmap> {
479 let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
480 supported_events.insert(EV_REL, virtio_input_bitmap::from_bits(&[REL_WHEEL]));
481 supported_events
482 }
483
484 #[cfg(test)]
485 mod tests {
486 use super::*;
487
488 #[test]
test_new_switches_config()489 fn test_new_switches_config() {
490 let config = new_switches_config(0);
491 assert_eq!(config.serial_name, "virtio-switches-0");
492
493 let events = config.supported_events;
494 assert_eq!(events.len(), 1);
495 assert_eq!(events.contains_key(&EV_SW), true);
496
497 // The bitmap should contain SW_CNT=0x10+1=17 ones,
498 // where each one is packed into the u8 bitmap.
499 let mut expected_bitmap = [0_u8; 128];
500 expected_bitmap[0] = 0b11111111u8;
501 expected_bitmap[1] = 0b11111111u8;
502 expected_bitmap[2] = 0b1u8;
503 assert_eq!(events[&EV_SW].bitmap, expected_bitmap);
504 }
505 }
506