mirror of
https://github.com/datarhei/core.git
synced 2025-09-27 04:16:25 +08:00
136 lines
2.7 KiB
Go
136 lines
2.7 KiB
Go
package skills
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type fbformat struct {
|
|
bpp int
|
|
roffset int
|
|
goffset int
|
|
boffset int
|
|
aoffset int
|
|
format string
|
|
}
|
|
|
|
var fbformats []fbformat = []fbformat{
|
|
{32, 0, 8, 16, 24, "rgba"},
|
|
{32, 16, 8, 0, 24, "bgra"},
|
|
{32, 8, 16, 24, 0, "argb"},
|
|
{32, 3, 2, 8, 0, "abgr"},
|
|
{24, 0, 8, 16, 0, "rgb24"},
|
|
{24, 16, 8, 0, 0, "bgr24"},
|
|
{16, 11, 5, 0, 0, "rgb565le"},
|
|
{16, 0, 5, 11, 0, "rgb565be"},
|
|
}
|
|
|
|
// DevicesFramebuffer returns a list of framebuffer devices found on the system
|
|
func DevicesFramebuffer() ([]HWDevice, error) {
|
|
devices := []HWDevice{}
|
|
|
|
for i := 0; i < 32; i++ {
|
|
path := fmt.Sprintf("/dev/fb%d", i)
|
|
_, err := os.Stat(path)
|
|
if err != nil {
|
|
break
|
|
}
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
cmd := exec.Command("fbset", "-s", "-fb", path)
|
|
cmd.Env = []string{}
|
|
cmd.Stdout = buf
|
|
cmd.Run()
|
|
|
|
device := HWDevice{
|
|
Id: path,
|
|
Name: path,
|
|
Extra: parseFramebufferDevice(buf),
|
|
Media: "video",
|
|
}
|
|
|
|
devices = append(devices, device)
|
|
}
|
|
|
|
return devices, nil
|
|
}
|
|
|
|
func parseFramebufferDevice(data *bytes.Buffer) string {
|
|
reGeometry := regexp.MustCompile(`geometry ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)`)
|
|
reRGBA := regexp.MustCompile(`rgba ([0-9]+/[0-9]+),([0-9]+/[0-9]+),([0-9]+/[0-9]+),([0-9]+/[0-9]+)`)
|
|
|
|
geometry := ""
|
|
format := fbformat{}
|
|
|
|
scanner := bufio.NewScanner(data)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
|
|
matches := reGeometry.FindStringSubmatch(line)
|
|
if matches != nil {
|
|
geometry = fmt.Sprintf("%sx%s", matches[1], matches[2])
|
|
if matches[1] != matches[3] || matches[2] != matches[4] {
|
|
geometry += fmt.Sprintf(" (%sx%s)", matches[3], matches[4])
|
|
}
|
|
|
|
if x, err := strconv.Atoi(matches[5]); err == nil {
|
|
format.bpp = x
|
|
}
|
|
}
|
|
|
|
matches = reRGBA.FindStringSubmatch(line)
|
|
if matches != nil {
|
|
format.roffset = parseFramebufferDeviceOffset(matches[1])
|
|
format.goffset = parseFramebufferDeviceOffset(matches[2])
|
|
format.boffset = parseFramebufferDeviceOffset(matches[3])
|
|
format.aoffset = parseFramebufferDeviceOffset(matches[4])
|
|
}
|
|
}
|
|
|
|
if len(geometry) == 0 || format.bpp == 0 {
|
|
return ""
|
|
}
|
|
|
|
for _, f := range fbformats {
|
|
if f.bpp == format.bpp && f.roffset == format.roffset && f.goffset == format.goffset && f.boffset == format.boffset {
|
|
return geometry + " " + f.format
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func parseFramebufferDeviceOffset(format string) int {
|
|
c := strings.Split(format, "/")
|
|
|
|
bits := 0
|
|
offset := 0
|
|
|
|
if x, err := strconv.Atoi(c[0]); err == nil {
|
|
bits = x
|
|
} else {
|
|
return 0
|
|
}
|
|
|
|
if x, err := strconv.Atoi(c[1]); err == nil {
|
|
offset = x
|
|
} else {
|
|
return 0
|
|
}
|
|
|
|
if bits == 0 {
|
|
return 0
|
|
}
|
|
|
|
return offset
|
|
}
|