v0.1.0 d9218d6

edid.go RawHistoryFolder

1package drm
2
3import (
4	"bufio"
5	"os"
6	"path/filepath"
7	"strings"
8)
9
10// Monitor identifies the display attached to a connector.
11type Monitor struct {
12	Make, Model, Serial string
13}
14
15// readMonitor parses the connector's EDID from sysfs. Missing data yields "Unknown".
16func readMonitor(card, connector string) Monitor {
17	data, err := os.ReadFile(filepath.Join("/sys/class/drm", filepath.Base(card)+"-"+connector, "edid"))
18	if err != nil {
19		return Monitor{Make: "Unknown", Model: "Unknown"}
20	}
21	return parseEDID(data)
22}
23
24func parseEDID(d []byte) Monitor {
25	m := Monitor{Make: "Unknown", Model: "Unknown"}
26	if len(d) < 128 || string(d[:8]) != "\x00\xff\xff\xff\xff\xff\xff\x00" {
27		return m
28	}
29	id := uint16(d[8])<<8 | uint16(d[9])
30	pnp := string([]byte{byte(id>>10&0x1f) + '@', byte(id>>5&0x1f) + '@', byte(id&0x1f) + '@'})
31	m.Make = pnpName(pnp)
32	// Display descriptors: 0xFC name, 0xFF serial.
33	for off := 54; off+18 <= 126; off += 18 {
34		b := d[off : off+18]
35		if b[0] != 0 || b[1] != 0 {
36			continue
37		}
38		text := strings.TrimRight(strings.SplitN(string(b[5:18]), "\n", 2)[0], " ")
39		switch b[3] {
40		case 0xfc:
41			m.Model = text
42		case 0xff:
43			m.Serial = text
44		}
45	}
46	return m
47}
48
49// pnpName maps a PNP id to a vendor name via hwdata, falling back to the id.
50func pnpName(id string) string {
51	f, err := os.Open("/usr/share/hwdata/pnp.ids")
52	if err != nil {
53		return id
54	}
55	defer f.Close()
56	s := bufio.NewScanner(f)
57	for s.Scan() {
58		if name, ok := strings.CutPrefix(s.Text(), id+"\t"); ok {
59			return name
60		}
61	}
62	return id
63}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 23

Tags 10

↑↓ moveenter openesc close