blob: b198a1e227783371564bc715bf0222f7ef31b6bf [file] [log] [blame] [view] [edit]
# kmsvnc Design notes
[TOC]
## Background
Long time ago VNC used to work on Chromebooks, when X11 was being used on DUT,
but with freon migration we lost that feature.
The current workaround is to use Chrome Remote Desktop on Chrome OS devices,
which does not work on the login screen. We have tast test dev.RemoteDesktop
which tries to automate logging in and starting Chrome Remote Desktop, it is
brittle because it relies on UI, and UI needs to be in English US, but it works
when it works.
Most of the time we just do with having the DUT locally or not watching the
display.
Betty is a board for running as virtual machines. Qemu can run betty images and
Qemu provides a VNC server capability. We found that GCE can run betty images
too, but does not provide a VNC server capability, and nested virtualization
running qemu on GCE was too slow for our use case, hence we needed VNC
capability more than before.
## Goals
Have VNC working on betty so that developers have the option of what is on the
display, and interact. Ideally I can see the login screen also so that I can log
in via VNC in a similar manner to qemu VNC.
## Detailed Design
### VNC server
We rely on libvncserver for the details of VNC serving. kmsvnc provides the
device manipulation specific to chromebooks.
### Authentication
kmsvnc does not provide authentication mechanism, and defers authentication to
ssh and its port forwarding feature already available on Chromebooks.
### Grabbing screen
We use KMS/DRM for grabbing the current display.
For devices that expose capability of capturing multiple planes we support
scanning multiple planes and merging.
There are two major types of boards that this code handles.
#### getfb2-capable
framebuffer is converted every frame to ARGB format using EGL call. This only
depends on getfb2 ioctl being available (kernel 4.4 or later).
The last known device with this configuration is hana.
#### getfb2-capable and atomic_modeset capable
planes are scanned and merged so that when multiple planes are being used they
are correctly rendered. This needs getfb2 and in addition support for
`DRM_CLIENT_CAP_ATOMIC`.
Development was done typically with rammus.
### Display orientation
Tablets can be rotated, you can pass --rotate to `screenshot` and `kmsvnc`
to rotate the captured screeen 90 degrees clockwise. This works correctly
with `kukui` devices. Other orientations are not supported at this moment
in the sprit of YAGNI.
### Keyboard handling
The [RFB protocol](https://tools.ietf.org/html/rfc6143#section-7.5.4) follows
the X11 protocol for keyboard handling. Upon receiving an
[X11 key symbol](https://cgit.freedesktop.org/xorg/proto/x11proto/tree/keysymdef.h)
on server-side, we map them back to
[Linux input keycodes](https://chromium.googlesource.com/chromiumos/third_party/kernel/+/v4.4/include/uapi/linux/input-event-codes.h),
and emit input events using a virtual keyboard device created via the Linux
uinput module.
The protocol is defined such that, if the input keystroke effectively types an
ASCII char on the client, the char is sent directly to the server as the X11
keysym. For example when the user types the key `8`, the server would receive
`8` as the keysym. However when the user types 8 while holding Shift, the
server would receive (assuming US layout) `*`. We need to map both `8` and `*`
into `KEY_8`.
Note that some keys map to ASCII chars directly but are considered special in
X11, e.g. keypad symbols like `XK_KP_Multiply`. We observed that some clients
are not handling them correctly which may cause interop issues. For example
using VNC Viewer for Google Chrome, when the keypad `*` key is pressed, it sends
`*` directly instead of `XK_KP_Multiply`, and maps to `KEY_8` in our
implementation.
### Mouse handling
The server receives pointer events with their absolute coordinates according to
screen size. Similar to the keyboard, we create a virtual uinput device for
those events. However its nontrivial to emulate a mouse since
- Linux expects relative x/y movements from the mouse, not absolute positions
- We dont know the initial position of the mouse
- In Chrome theres pointer acceleration, we dont know the actual pointer
position after a mouse move event
Weve ended up emulating a touch screen device so we can send touch events with
absolute coordinates. Only left click tapping works. Drag & drop works.
(Actually the QEMU VNC server uses the same approach, its Chromes fault that
it assumes touchscreens cant emit `BTN_RIGHT` events.)