| # 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 it’s nontrivial to emulate a mouse since | |
| - Linux expects relative x/y movements from the mouse, not absolute positions | |
| - We don’t know the initial position of the mouse | |
| - In Chrome there’s pointer acceleration, we don’t know the actual pointer | |
| position after a mouse move event | |
| We’ve 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, it’s Chrome’s fault that | |
| it assumes touchscreens can’t emit `BTN_RIGHT` events.) |