...
1 package drm
2
3 import (
4 "fmt"
5 "os"
6 "path"
7 "regexp"
8 "strconv"
9 "strings"
10
11 "edge-infra.dev/pkg/sds/lib/edid"
12 )
13
14 const DRMPath = "/sys/class/drm"
15
16 const (
17 SubSystem = "drm"
18 cardPrefix = "card"
19 edidFileName = "edid"
20 connectorPattern = "^card[0-9](-[A-Za-z0-9]+)+$"
21 )
22
23
24
25 type Connector struct {
26 card int
27 port string
28 edid *edid.EDID
29 }
30
31
32 func (connector Connector) String() string {
33 return fmt.Sprintf("%s%d-%s", cardPrefix, connector.card, connector.port)
34 }
35
36
37 func (connector Connector) Card() string {
38 return fmt.Sprintf("%s%d", cardPrefix, connector.card)
39 }
40
41
42 func (connector Connector) CardNum() int {
43 return connector.card
44 }
45
46
47 func (connector Connector) Port() string {
48 return connector.port
49 }
50
51
52 func (connector Connector) Path() string {
53 return path.Join(DRMPath, connector.String())
54 }
55
56
57 func (connector Connector) EDID() *edid.EDID {
58 return connector.edid
59 }
60
61
62 func (connector *Connector) WithEDID(edid *edid.EDID) {
63 connector.edid = edid
64 }
65
66 func NewConnector(name string) (*Connector, error) {
67 cardName, port, err := SplitConnectorName(name)
68 if err != nil {
69 return nil, err
70 }
71
72
73 card, err := strconv.Atoi(strings.TrimPrefix(cardName, cardPrefix))
74 if err != nil {
75 return nil, err
76 }
77
78 connector := &Connector{
79 card: card,
80 port: port,
81 }
82
83
84 edid, err := edid.NewFromFile(path.Join(connector.Path(), edidFileName))
85 if err == nil {
86 connector.edid = edid
87 }
88
89 return connector, nil
90 }
91
92
93
94 func SplitConnectorName(name string) (card, port string, err error) {
95 if err := ValidateConnectorName(name); err != nil {
96 return "", "", err
97 }
98 card, port, _ = strings.Cut(name, "-")
99 return card, port, nil
100 }
101
102
103
104 func ValidateConnectorName(name string) error {
105 re, err := regexp.Compile(connectorPattern)
106 if err != nil {
107 return err
108 }
109
110 if match := re.MatchString(name); !match {
111 return fmt.Errorf("%s is not a valid connector name", name)
112 }
113
114 return nil
115 }
116
117
118 func Connectors() ([]Connector, error) {
119 files, err := os.ReadDir(DRMPath)
120 if err != nil {
121 return nil, fmt.Errorf("failed to read directory %s: %w", DRMPath, err)
122 }
123
124 connectors := []Connector{}
125 for _, file := range files {
126 connector, err := NewConnector(file.Name())
127 if err == nil {
128 connectors = append(connectors, *connector)
129 }
130 }
131
132 return connectors, nil
133 }
134
View as plain text