devices/virtio/input/
defaults.rs

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
5use std::collections::BTreeMap;
6
7use base::warn;
8use linux_input_sys::constants::*;
9
10use super::virtio_input_absinfo;
11use super::virtio_input_bitmap;
12use super::virtio_input_device_ids;
13use 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.
17pub 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
36pub 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.
57pub 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.
70pub 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.
83pub 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.
96pub 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).
109pub 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.
130pub 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
159pub 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
186fn 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
193fn 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
200fn 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
219fn 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
236fn 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
261fn 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
294fn 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
301fn 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
311fn 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
324fn 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
451fn 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
478fn 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)]
485mod tests {
486    use super::*;
487
488    #[test]
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}